2017-05-06 67 views
0

我正在爲我的Laravel 5.4項目添加tinymce。我已經把它變成了一個全球組件。這工作正常。它應該做什麼,一切都很好。現在,當遵循Laracast最新的「使用TDD構建論壇」系列時,我想到我可以將該組件添加到回覆組件中,並在那裏使用它!是的..不。我是一個vue nub,所以我確信我錯過了一些明顯的東西。誰能幫忙?我甚至決定把全球視爲一個孩子的組成部分......也不是那裏的喜悅。vue 2全局組件在另一個內部調用不會渲染

vue上的調試工具chrome說它在那裏......但編輯器不會渲染。所以我有點困惑。我試過在不同的地方添加<slot>,這沒有任何改變。任何幫助將不勝感激!

謝謝大家!

代碼如下─

app.js:

Vue.component('flash', require('./components/Flash.vue')); 
Vue.component('reply', require('./components/Reply.vue')); 
Vue.component('tinymce-editor',require('./components/Tinymce.vue')); 

const app = new Vue({ 
    el: '#app', 
}); 

Tinymce.vue:

<template> 
    <textarea name="body" class="form-control" id="tinymce" v-text="body" rows="5"></textarea> 
</template> 

<script> 
    export default { 
     name: 'tinymce-editor', 
     props: { 
      body: { 
       default: 'Something to say, have you?' 
      } 
     }, 

     mounted: function() { 
      const self = this; 
      tinymce.init({ 
       menubar: false, 
       path_absolute: "/", 
       selector: "#tinymce", 
       entity_encoding: "raw", 
       toolbar_items_size: "small", 
       style_formats: [ 
        {"title": "Bold", "icon": "bold", "format": "bold"}, 
        {"title": "Italic", "icon": "italic", "format": "italic"}, 
        {"title": "Underline", "icon": "underline", "format": "underline"}, 
        {"title": "Strikethrough", "icon": "strikethrough", "format": "strikethrough"}, 
        {"title": "Superscript", "icon": "superscript", "format": "superscript"}, 
        {"title": "Subscript", "icon": "subscript", "format": "subscript"}, 
        {"title": "Code", "icon": "code", "format": "code"} 
       ], 
       plugins: 'advlist anchor autolink autoresize code colorpicker hr image link lists preview searchreplace spellchecker textcolor wordcount', 
       block_formats: "Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6;", 
       toolbar1: "undo redo | formatselect | bullist numlist | link unlink | uploadimg image", 
       toolbar2: "styleselect fontsizeselect | forecolor | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | outdent indent | removeformat", 
       init_instance_callback: function(editor) { 

        // init tinymce 
        editor.on('init', function() { 
         tinymce.activeEditor.setContent(self.value); 
        }); 
       } 
      }); 
     }, 
     update: function(newVal, oldVal) { 
      // set val and trigger event 
      $(this.el).val(newVal).trigger('keyup'); 
     } 
    } 
</script> 

Reply.vue:

<script> 
    import Favorite from './Favorite.vue'; 
    import Tinymce from './Tinymce.vue'; 
    export default { 
     name: 'Reply', 
     props: ['attributes'], 

     components: { 
      'favorite': Favorite, 
      'tinymce-editor': Tinymce 
     }, 

     data() { 
      return { 
       editing: false, 
       body: this.attributes.body 
      }; 
     }, 

     methods: { 
      update() { 
       axios.patch('/replies/' + this.attributes.id, { 
        body: this.body 
       }); 

       this.editing = false; 

       flash('Updated!'); 
      }, 

      destroy() { 
       axios.delete('/replies/' + this.attributes.id); 

       $(this.$el).fadeOut(300,() => { 
        flash('Your reply has been deleted.'); 
       }); 
      } 
     } 
    } 
</script> 

reply.blade.php:

<reply :attributes="{{ $reply }}" inline-template v-cloak> 
    <div id="reply-{{$reply->id}}" class="panel panel-default"> 
     <div class="panel-heading"> 
      <div class="level"> 
       <h5 class="flex"> 
        <a href="{{ route('profile',$reply->owner->name) }}"> 
         {{ $reply->owner->name }} 
        </a> said {{ $reply->created_at->diffForHumans() }}... 
       </h5> 

       <favorite :reply="{{$reply}}"></favorite> 
      </div> 
     </div> 
     <div class="panel-body"> 
      <div v-if="editing"> 
       <div class="form-group"> 
        <tinymce-editor body="{{ $reply->body }}"></tinymce-editor> 
       </div> 
       <button class="btn btn-xs btn-primary" @click="update">Update</button> 
       <button class="btn btn-xs btn-link" @click="editing = false">Cancel</button> 
      </div> 

      <div v-else v-html="body"></div> 
     </div> 
     @can('update', $reply) 
      <div class="panel-footer level"> 
       <button class="btn btn-xs btn-success mr-1" @click="editing = true">Edit</button> 
       <button class="btn btn-xs btn-danger mr-1" @click="destroy">Delete</button> 
      </div> 
     @endcan 
    </div> 
</reply> 
+0

沒有絕對的把握,但我認爲你應該命名組件TinymceEditor將其呈現爲即: 'Vue.component('TinymceEditor',require('./comp onents/Tinymce.vue'));' –

+0

由於TinymceEditor組件是在全局級別註冊的,因此無需在Reply.vue組件中再次導入TinymceEditor組件。嘗試刪除導入語句,並從Reply.vue – thanksd

+0

中的'components'屬性中刪除條目感謝您的提示,但這兩者都沒有幫助。它仍然沒有渲染。 – ThePoet444

回答

1

我終於明白了。這裏實際存在兩個問題。編輯者的ID不是唯一的。所以這就是爲什麼孩子編輯沒有渲染。一旦我解決了這個問題,我就有了孩子沒有更新父母的問題。所以我不得不解決這個問題。更新後的代碼可供任何其他需要它的人使用。這可能不是「最佳實踐」代碼,但它可以工作。我非常樂意改進!謝謝大家!

Reply.vue:

<script> 
    import Favorite from './Favorite.vue'; 

    export default { 
     name: 'Reply', 
     props: ['attributes'], 

     components: { 
      'favorite': Favorite, 
     }, 

     data() { 
      return { 
       editing: false, 
       body: this.attributes.body 
      }; 
     }, 

     methods: { 
      updateBody(newContent) { 
       this.body = newContent; 
      }, 

      update() { 
       axios.patch('/replies/' + this.attributes.id, { 
        body: this.body 
       }); 

       this.editing = false; 

       flash('Updated!'); 
      }, 

      destroy() { 
       axios.delete('/replies/' + this.attributes.id); 

       $(this.$el).fadeOut(300,() => { 
        flash('Your reply has been deleted.'); 
       }); 
      } 
     } 
    } 
</script> 

Tinymce.vue:

<template> 
    <textarea :id="id" name="body" class="form-control" rows="5" >{{ body }}</textarea> 
</template> 

<script> 
    export default { 
     name: 'tinymce-editor', 
     props: { 
      body: { 
       default: 'Something to say, have you?' 
      } 
     }, 

     data(){ 
      return { 
       id: 'tinymce-'+Date.now(), 
      } 
     }, 

     mounted: function() { 
      const self = this; 
      tinymce.init({ 
       menubar: false, 
       path_absolute: "/", 
       selector: '#'+self.id, 
       entity_encoding: "raw", 
       toolbar_items_size: "small", 
       style_formats: [ 
        {"title": "Bold", "icon": "bold", "format": "bold"}, 
        {"title": "Italic", "icon": "italic", "format": "italic"}, 
        {"title": "Underline", "icon": "underline", "format": "underline"}, 
        {"title": "Strikethrough", "icon": "strikethrough", "format": "strikethrough"}, 
        {"title": "Superscript", "icon": "superscript", "format": "superscript"}, 
        {"title": "Subscript", "icon": "subscript", "format": "subscript"}, 
        {"title": "Code", "icon": "code", "format": "code"} 
       ], 
       plugins: 'advlist anchor autolink autoresize code colorpicker hr image link lists preview searchreplace spellchecker textcolor wordcount', 
       block_formats: "Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6;", 
       toolbar1: "undo redo | formatselect | bullist numlist | link unlink | uploadimg image", 
       toolbar2: "styleselect fontsizeselect | forecolor | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | outdent indent | removeformat", 
       init_instance_callback: function(editor) { 

        // init tinymce 
        editor.on('init', function() { 
         tinymce.editors[self.id].setContent(self.body); 
        }); 

        editor.on('keyup', function() { 
         const newContent = tinymce.editors[self.id].getContent(); 

         // Fire an event to let its parent know 
         self.$emit('content-updated', newContent); 
        }); 
       } 
      }); 
     }, 

     update: function() { 
      const self = this; 

      if (self.body) { 
       tinymce.editors[self.id].setContent(self.body); 
      } 
     }, 

     beforeDestroy: function(){ 
      tinymce.remove(this.id) 
     } 
    } 
</script> 

reply.blade.php:

<reply :attributes="{{ $reply }}" inline-template v-cloak> 
    <div id="reply-{{$reply->id}}" class="panel panel-default"> 
     <div class="panel-heading"> 
      <div class="level"> 
       <h5 class="flex"> 
        <a href="{{ route('profile',$reply->owner->name) }}"> 
         {{ $reply->owner->name }} 
        </a> said {{ $reply->created_at->diffForHumans() }}... 
       </h5> 

       <favorite :reply="{{$reply}}"></favorite> 
      </div> 
     </div> 
     <div class="panel-body"> 
      <div v-if="editing"> 
       <div class="form-group"> 
        <tinymce-editor v-model="body" body="{{ $reply->body }}" v-on:content-updated="updateBody"></tinymce-editor> 
       </div> 
       <button class="btn btn-xs btn-primary" @click="update">Update</button> 
       <button class="btn btn-xs btn-link" @click="editing = false">Cancel</button> 
      </div> 

      <div v-else v-html="body"></div> 
     </div> 
     @can('update', $reply) 
      <div class="panel-footer level"> 
       <button class="btn btn-xs btn-success mr-1" @click="editing = true">Edit</button> 
       <button class="btn btn-xs btn-danger mr-1" @click="destroy">Delete</button> 
      </div> 
     @endcan 
    </div> 
</reply>