【问题标题】:vue 2 global compoenent called inside another won't render在另一个内部调用的 vue 2 全局组件不会呈现
【发布时间】:2017-05-06 12:59:22
【问题描述】:

我正在将 tinymce 添加到我的 Laravel 5.4 项目中。我已经把它变成了一个全球性的组成部分。这工作正常。做它应该做的,一切都很好。现在,当关注 Laracasts 最新的“使用 TDD 构建论坛”系列时。我开始想我可以将该组件添加到回复组件中并在那里使用它!是的。。不。我是一个 vue nub,所以我确定我遗漏了一些明显的东西。任何人都可以帮忙吗?我什至决定将 global 也称为子组件.. 那里也没有乐趣。

chrome 上的 Vue 调试工具说它在那里……但编辑器不会渲染。所以我有点困惑。我也尝试将<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>

回复.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>

回复.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>

【问题讨论】:

  • 不确定,但我认为您应该将组件命名为 TinymceEditor 以便将其呈现为 这意味着:Vue.component('TinymceEditor',require('./components/Tinymce.vue'));
  • 由于TinymceEditor组件是在全局级别注册的,所以不需要在Reply.vue组件中再次导入。尝试删除 import 语句并从 Reply.vue 中的 components 属性中删除条目
  • 感谢您的提示,但都没有帮助。它仍然没有渲染。

标签: laravel-5 vuejs2


【解决方案1】:

我终于明白了。这里实际上有两个问题。编辑器上的 ID 不是唯一的。所以这就是子编辑器没有渲染的原因。一旦我解决了这个问题,我就有了孩子没有更新父母的问题。所以我也必须解决这个问题。为其他可能想要的人更新了下面的代码。这可能不是“最佳实践”代码,但它有效。我非常愿意改进!谢谢大家!

回复.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>

回复.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>

【讨论】:

    猜你喜欢
    • 2021-05-30
    • 2021-02-14
    • 2020-12-24
    • 2016-08-02
    • 1970-01-01
    • 2020-06-19
    • 2018-06-04
    • 2019-02-20
    • 1970-01-01
    相关资源
    最近更新 更多