zoukankan      html  css  js  c++  java
  • 07.vue-charp-07 组件详解(一)

    组件的注册

    <body>
        <div id="app1">
            <h1>app1</h1>
            <my-global-componet></my-global-componet>
            <app1-my-component></app1-my-component>
            <table>
                <p>Vue组件的模板在某些情况下会受到HTML的限制,比如
                    table内规定只允许是tr、td、
                    th等这些表格元素,
                    所以在table内直接使用组件是无效的。这种情况下,可以使用特殊的is属性来挂载组件</p>
                <tbody is="my-global-componet"></tbody>
            </table>
        </div>
        <div id="app2">
            <h1>app2</h1>
            <my-global-componet></my-global-componet>
            <app1-my-component></app1-my-component>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            //全局注册组件
            Vue.component('my-global-componet', {
                template: '<div>这里是全局组件的内容</div>'
            });
    
            var app1 = new Vue({
                el: '#app1',
                components: {
                    'app1-my-component': {
                        template: '<div>app1的局部组件,只能在 app1 中使用</div>'
                    }
                },
                data: {
                }
            })
    
            var app2 = new Vue({
                el: '#app2',
                data: {
                }
            })
        </script>
    </body>
    
    • 全局注册组件 Vue.component()

    • 局部组件:new Vue({components:...})

    • is="my-global-componet"

      Vue组件的模板在某些情况下会受到HTML的限制,比如table内规定只允许是tr、td、 th等这些表格元素,所以在table内直接使用组件是无效的。这种情况下,可以使用特殊的is属性来挂载组件

    组件的选项

    data

    组件的data必须是函数,然后将数据return出去

    <body>
        <div id="app">
            <my-global-componet></my-global-componet>
            <my-global-componet></my-global-componet>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-global-componet', {
                template: '<div> 
                              组件的data.message:{{message}} 
                              <button @click="count++">组件的data.count:{{ count }}</button> 
                              <button @click="count++">组件的data.count:{{ count }}</button> 
                         </div>',
                data: function () {
                    //组件的data必须是函数,然后将数据return出去,
                    return {
                        message: '组件的内容!!!',
                        count: 0
                    }
                }
            });
    
            var app = new Vue({
                el: '#app'
            })
    
        </script>
    </body>
    

    使用props传递数据

    props传递数据之数组

    
    <body>
        <div id="app">
            <h1>组件</h1>
            <my-componet message="来自父组件的数据1" warming-text="来自父组件的数据2" :pare-msg="parentDynamicMsg">
            </my-componet>
            <h1>父页面</h1>
            <input type="text" v-model="parentDynamicMsg">
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-componet', {
                template: '<div> 
                              <p>message:{{message}}</p> 
                              <p>warmingText:{{warmingText}}</p> 
                              <p>pareMsg:{{pareMsg}}</p> 
                          <div>',
                props: ['message', 'warmingText', 'pareMsg'] //驼峰命名(camelCase)的props名称要转为短横分隔命名
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    parentDynamicMsg: "来自父组件的动态数据"
                }
            })
    
        </script>
    </body>
    
    • 使用【字符串数组】来定义组件的一系列属性:props: ['message', 'warmingText', 'pareMsg']
    • 属性命名规则:驼峰命名(camelCase)的props名称要转为短横分隔命名
    • 使用v-bing:绑定来自父组件的动态数据,:pare-msg="parentDynamicMsg"

    props传递数据之对象

    参见 数据验证

    单向数据流

    Vue 2.x与Vue 1.x比较大的一个改变就是,Vue 2.x通过props传递数据是单向的了,也就是父组件数据变化时会传递给子组件,但是反过来不行。而在Vue 1.x里提供了.sync修饰符来支持双向绑定。

    <body>
        <div id="app">
            <h1>组件</h1>
            <my-componet :pare-msg="parentDynamicMsg">
            </my-componet>
            <h1>父页面</h1>
            <input type="text" v-model="parentDynamicMsg">
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-componet', {
                template: '<div> 
                              <p>pareMsg:{{pareMsg}}</p> 
                              <input type="text" v-model="pareMsg">
                          </div>',
                props: ['pareMsg']
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    parentDynamicMsg: "来自父组件的动态数据"
                }
            })
    
        </script>
    </body>
    

    在组件中修改pareMsg的值并不会影响到 父组件parentDynamicMsg的值

    如何使组件的值独立

    <body>
        <div id="app">
            <h1>组件</h1>
            <my-componet :pare-msg="parentDynamicMsg">
            </my-componet>
            <h1>父页面</h1>
            <input type="text" v-model="parentDynamicMsg">
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-componet', {
                template: '<div> 
                              <p>myComponetMessage:{{myComponetMessage}}</p> 
                              <input type="text" v-model="myComponetMessage">
                          </div>',
                props: ['pareMsg'],
                data: function () {
                    return {
                        myComponetMessage: this.pareMsg //之后myComponetMessage就父组件的parentDynamicMsg无关,两者互不影响
                    }
                }
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    parentDynamicMsg: "来自父组件的动态数据"
                }
            })
    
        </script>
    </body>
    

    在组件的data定义一个变量myComponetMessage引用属性pareMsg,之后myComponetMessage就父组件的parentDynamicMsg无关,两者互不影响

    组件的计算属性

    <body>
        <div id="app">
            <h1>组件</h1>
            <my-componet :my-width="componentWidth">
            </my-componet>
            <h1>父页面</h1>
            <input type="text" v-model="componentWidth" placeholder="请输入宽度">
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-componet', {
                template: '<div> 
                              <input type="text" :style="styles" :value="myWidth"/> 
                          </div>',
                props: ['myWidth'],
                computed: {
                    styles: function () {
                        return {
                            color: 'red',
                             this.myWidth + 'px'
                        }
                    }
                }
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    componentWidth: 100
                }
            })
        </script>
    </body>
    

    父组件的componentWidth无单位px,在组件中通过计算属性styles.width 把单位px补上

    数据验证

    我们上面所介绍的props选项的值都是一个数组,一开始也介绍过,除了数组外,还可以是对象,当prop需要验证时,就需要对象写法。
    一般当你的组件需要提供给别人使用时,推荐都进行数据验证,比如某个数据必须是数字类型,如果传入字符串,就会在控制台弹出警告。

    (示例略)

    组件数据传递之-对象

    <body>
        <div id="app">
            <my-list :cpt-books="mybooks" :cpt-msg="myMsg"></my-list>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-list', {
                template: '<div> 
                                <h1>cptMsg={{cptMsg}}</h1> 
                                <ul>
                                    <li v-for="book in cptBooks">{{book.name}}</li> 
                                </ul>
                           </div>',
                props: {
                    cptMsg: {
                        type: String,
                        default: function () {
                            return "--";
                        }
                    },
                    cptBooks: {
                        type: Array,
                        default: function () {
                            return [];
                        }
                    }
                }
    
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    myMsg: "来自父组件的消息",
                    mybooks: [
                        { name: '《Vue.js实战》' },
                        { name: '《JavaScript语言精粹》' },
                        { name: '《JavaScript高级程序设计》' }
                    ]
                }
            })
        </script>
    </body>
    

    组件通信

    从父组件向子组件通信,通过props传递数据就可以了,但Vue组件通信的场景不止有这一种,

    组件关系可分为

    • 父子组件通信、
    • 兄弟组件通信、
    • 跨级组件通信。

    本节将介绍各种组件之间通信的方法。

    自定义事件

    当子组件需要向父组件传递数据时,就要用到自定义事件。我们在介绍指令v-on时有提到,v-on除了监听DOM事件外,还可以用于组件之间的自定义事件。

    • 子组件用$emit()来触发事件,

    • 父组件用$on()来监听子组件的事件。
      父组件也可以直接在子组件的自定义标签上使用v-on来监听子组件触发的自定义事件,

    <body>
        <div id="app">
            <h1>组件</h1>
            <my-componet @increase="handleGetTotal" @reduce="handleGetTotal">
            </my-componet>
            <h1>父组件</h1>
            <p>total={{total}}</p>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-componet', {
                template: '<div> 
                              <button @click="handleIncrease">+1</button> 
                              <button @click="handleReduce">-1</button> 
                          </div>',
                data: function () {
                    return {
                        counter: 0
                    }
                },
                methods: {
                    handleIncrease: function () {
                        this.counter++;
                        //发起自定义事件
                        this.$emit('increase', this.counter);
                    },
                    handleReduce: function () {
                        this.counter--;
                        //发起自定义事件
                        this.$emit('reduce', this.counter);
                    },
                },
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    total: 0
                }, methods: {
                    handleGetTotal: function (total) {
                        this.total = total;
                    }
                }
            })
        </script>
    </body>
    
    • 发起自定义事件,参数可以是若干个

    ​ this.$emit('increase', this.counter);

    子组件向父组件传递数据-使用v-model和input事件名

    <body>
        <div id="app">
            <h1>组件</h1>
            <my-componet v-model="total">
            </my-componet>
            <h1>父组件</h1>
            <p>total={{total}}</p>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-componet', {
                template: '<div> 
                              <button @click="handleIncrease">+1</button> 
                              <button @click="handleReduce">-1</button> 
                          </div>',
                data: function () {
                    return {
                        counter: 0
                    }
                },
                methods: {
                    handleIncrease: function () {
                        this.counter++;
                        this.$emit('input', this.counter);
                    },
                    handleReduce: function () {
                        this.counter--;
                        this.$emit('input', this.counter);
                    },
                },
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    total: 0
                }
            })
        </script>
    </body>
    

    ​ 子组件向父组件传递数据-使用v-model时,事件名必须是input

    任何组件传递数据

    在Vue.js 2.x中,推荐使用一个空的Vue实例作为中央事件总线(bus),也就是一个中介。

    <body>
        <div id="app">
            <h1>组件</h1>
            <my-componet></my-componet>
            <h1>父组件</h1>
            <p>total={{total}}</p>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            //1.使用一个空的Vue实例作为中央事件总线(bus)
            var bus = new Vue();
            Vue.component('my-componet', {
                template: '<div> 
                              <button @click="handleIncrease">+1</button> 
                              <button @click="handleReduce">-1</button> 
                          </div>',
                data: function () {
                    return {
                        counter: 0
                    }
                },
                methods: {
                    handleIncrease: function () {
                        this.counter++;
                        //2.bus发起事件
                        bus.$emit('on-counter-change', this.counter);
                    },
                    handleReduce: function () {
                        this.counter--;
                        //2.bus发起事件
                        bus.$emit('on-counter-change', this.counter);
                    },
                },
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    total: 0
                }, mounted: function () {
                    let _this = this;
                    //3.bus监听事件
                    bus.$on('on-counter-change', function (counter) {
                        _this.total = counter;
                    })
                }
            })
        </script>
    </body>
    

    首先创建了一个名为bus的空Vue实例,里面没有任何内容;

    组件间通信-父链

    在子组件中,使用this.$parent可以直接访问该组件的父实例或组件,父组件也可以通过this.$children访问它所有的子组件,而且可以递归向上或向下无限访问,直到根实例或最内层的组件

    <body>
        <div id="app">
            <h1>组件</h1>
            <my-componet></my-componet>
            <h1>父组件</h1>
            <p>total={{total}}</p>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
    
            Vue.component('my-componet', {
                template: '<div> 
                              <button @click="handleIncrease">+1</button> 
                              <button @click="handleReduce">-1</button> 
                          </div>',
                data: function () {
                    return {
                        counter: 0
                    }
                },
                methods: {
                    handleIncrease: function () {
                        this.$parent.total++;
                    },
                    handleReduce: function () {
                        this.$parent.total++;
                    },
                },
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    total: 0
                }
            })
        </script>
    </body>
    

    尽管Vue允许这样操作,但在业务中,子组件应该尽可能地避免依赖父组件的数据,更不应该去主动修改它的数据,因为这样使得父子组件紧耦合,只看父组件,很难理解父组件的状态,因为它可能被任意组件修改,理想情况下,只有组件自己能修改它的状态。父子组件最好还是通过props和$emit来通信。

    组件间通信-组件索引

    当子组件较多时,通过this.$children来一一遍历出我们需要的一个组件实例是比较困难的,尤其是组件动态渲染时,它们的序列是不固定的。Vue提供了子组件索引的方法,用特殊的属性ref来为子组件指定一个索引名称

    <body>
        <div id="app">
            <h1>组件</h1>
            <my-componet ref="refMyComponent"></my-componet>
            <h1>父组件</h1>
            <button @click="handleIncrease">+1</button>
            <button @click="handleReduce">-1</button>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
    
            Vue.component('my-componet', {
                template: '<div> 
                              counter={{counter}} 
                          </div>',
                data: function () {
                    return {
                        counter: 0
                    }
                }
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    total: 0
                },
                methods: {
                    handleIncrease: function () {
                        this.$refs.refMyComponent.counter++;
                    },
                    handleReduce: function () {
                        this.$refs.refMyComponent.counter--
                    },
                }
            })
        </script>
    </body>
    
    
    • <my-componet ref="refMyComponent"></my-componet>
    • this.$refs.refMyComponent.counter++;

    $refs只在组件渲染完成后才填充,并且它是非响应式的。它仅仅作为一个直接访问子组件的应急方案,应当避免在模板或计算属性中使用$refs。

    什么是slot

    当需要让组件组合使用,混合父组件的内容与子组件的模板时,就会用到slot,这个过程叫作内容分发(transclusion)。以<app>为例,它有两个特点:<app>组件不知道它的挂载点会有什么内容。挂载点的内容是由<app>的父组件决定的。<app>组件很可能有它自己的模板。
    props传递数据、events触发事件和slot内容分发就构成了Vue组件的3个API来源,再复杂的组件也是由这3部分构成的。

    单个slot

    在子组件内使用特殊的<slot>元素就可以为这个子组件开启一个slot(插槽),在父组件模板里,插入在子组件标签内的所有内容将替代子组件的<slot> 标签及它的内容。

    <body>
        <div id="app">
            <my-componet></my-componet>
            <my-componet>
                <p>父子组件内容</p>
            </my-componet>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
    
            Vue.component('my-componet', {
                template: '<div> 
                              <slot>如果父组件没有插入内容,我将作为默认出现</slot> 
                          </div>'
            });
    
            var app = new Vue({
                el: '#app'
            })
        </script>
    </body>
    

    具名slot

    <slot>元素指定一个name后可以分发多个内容,具名Slot可以与单个Slot共存

    <body>
        <div id="app">
            <my-componet>
                <h2 slot="header">标题</h2>
                <p>正文内容</p>
                <p>更多的正文内容</p>
                <div slot="footer">底部信息</div>
            </my-componet>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
    
            Vue.component('my-componet', {
                template: '<div class="container"> 
                              <div class="header"> 
                                  <slot name="header">slot中的默认标题</slot> 
                              </div> 
                              <div class="main"> 
                                  <slot></slot> 
                              </div> 
                              <div class="main2"> 
                                  <slot></slot> 
                              </div> 
                              <div class="footer"> 
                                  <slot name="footer"></slot> 
                              </div> 
                          </div>'
            });
    
            var app = new Vue({
                el: '#app'
            })
        </script>
    </body>
    

    html最后被解析为

        <div id="app">
            <div class="container">
                <div class="header">
                    <h2>标题</h2>
                </div>
                <div class="main">
                    <p>正文内容</p>
                    <p>更多的正文内容</p>
                </div>
                <div class="main2">
                    <p>正文内容</p>
                    <p>更多的正文内容</p>
                </div>
                <div class="footer">
                    <div>底部信息</div>
                </div>
            </div>
        </div>
    

    <slot> 没有使用name特性,它将作为默认slot出现,父组件没有使用slot特性的元素与内容都将出现在这里。
    如果没有指定默认的匿名slot,父组件内多余的内容片段都将被抛弃。

    作用域插槽

    作用域插槽是一种特殊的slot,使用一个可以复用的模板替换已渲染元素。

    <body>
        <div id="app">
            <my-componet>
                <template slot-scope="props">
                    <p>来自父组件的内容</p>
                    <p>{{props.msg}}</p>
                </template>
            </my-componet>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
    
            Vue.component('my-componet', {
                template: '<div class="container"> 
                               <slot msg="来自子组件的内容"></slot> 
                          </div>'
            });
    
            var app = new Vue({
                el: '#app'
            })
        </script>
    </body>
    
    • scope="this api replaced by slot-scope in 2.5.0+",使用slot-scope

    观察子组件的模板,在<slot>元素上有一个类似props传递数据给组件的写法msg="xxx",将数据传到了插槽。父组件中使用了<template>元素,而且拥有一个scope="props"的特性,这里的props 只是一个临时变量,就像v-for="item in items"里面的item一样。template内可以通过临时变量 props 访问来自子组件插槽的数据msg。

    • 作用域插槽更具代表性的用例是列表组件,允许组件自定义应该如何渲染列表每一项。
    <body>
        <div id="app">
            <my-list :cptbooks="mybooks">
                <!-- 作用域插槽也可以是具名的Slot -->
                <template slot="book" slot-scope="props">
                    <li>{{ props.bookName }}</li>
                </template>
            </my-list>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-list', {
                props: {
                    cptbooks: {
                        type: Array,
                        default: function () {
                            return [];
                        }
                    }
                },
                template: '
            <ul>
                <slot name="book"
                    v-for="book in cptbooks"
                    :book-name="book.name">
                    <!-- 这里也可以写默认 slot内容 -->
                </slot>
            </ul> '
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    mybooks: [
                        { name: '《Vue.js实战》' },
                        { name: '《JavaScript语言精粹》' },
                        { name: '《JavaScript高级程序设计》' }
                    ]
                }
            })
        </script>
    </body>
    
    

    访问slot

    Vue.js 2.x提供了用来访问被slot分发的内容的方法·$slots

    <body>
        <div id="app">
            <my-componet>
                <h2 slot="header">标题</h2>
                <p>正文内容</p>
                <p>更多的正文内容</p>
                <div slot="footer">底部信息</div>
            </my-componet>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
    
            Vue.component('my-componet', {
                template: '<div class="container"> 
                              <div class="header"> 
                                  <slot name="header">slot中的默认标题</slot> 
                              </div> 
                              <div class="main"> 
                                  <slot></slot> 
                              </div> 
                              <div class="footer"> 
                                  <slot name="footer"></slot> 
                              </div> 
                          </div>',
                mounted: function () {
                    /*
                    使用$slot.访问slot
                    */
                    var header = this.$slots.header;
                    var main = this.$slots.default;
                    var footer = this.$slots.footer;
                    console.log(footer);
                    console.log(footer[0].elm.innerHTML);
                }
            });
    
            var app = new Vue({
                el: '#app'
            })
        </script>
    </body>
    

    通过$slots可以访问某个具名slot,this.$slots.default包括了所有没有被包含在具名slot中的节点。尝试编写代码,查看两个console 打印的内容。
    $slots在业务中几乎用不到,在用render函数(进阶篇中将介绍)创建组件时会比较有用,但主要还是用于独立组件开发中。

    组件高级用法

    递归组件

    组件在它的模板内可以递归地调用自己,只要给组件设置name的选项就可以了

    设置name后,在组件模板内就可以递归使用了,不过需要注意的是,必须给一个条件来限制递归数量,否则会抛出错误:max stack size exceeded。

    <body>
        <div id="app">
            <my-component :count="appAcount"></my-component>
            <button @click="add()">+1</button>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-component', {
                name: "my-component",
                template: '
                        <div>
                            {{count}} 
                            <my-component :count="count + 1" v-if="count < 5"> </my-component> 
                        </div> '
                , props: {
                    count: {
                        type: Number,
                        default: 0
                    }
                }
    
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    appAcount: 1
                }, methods: {
                    add: function () {
                        this.appAcount++;
                    }
                },
            })
        </script>
    </body>
    

    组件递归使用可以用来开发一些具有未知层级关系的独立组件,比如级联选择器和树形控件等

    内联模板

    
    <body>
        <div id="app">
            <child-component inline-template>
                <div>
                    <h2>在父组件中定义子组件的模板</h2>
                    <p>{{ message }}</p>
                    <p>{{ msg }}</p>
                </div>
            </child-component>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('child-component', {
                data: function () {
                    return {
                        msg: '在子组件声明的数据'
                    }
                }
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    message: '在父组件声明的数据'
                }
            });
        </script>
    </body>
    

    组件的模板一般都是在template选项内定义的,Vue提供了一个内联模板的功能,在使用组件时,给组件标签使用inline-template特性,组件就会把它的内容当作模板,而不是把它当内容分发,这让模板更灵活。

    在父组件中声明的数据message和子组件中声明的数据msg,两个都可以渲染(如果同名,优先使用子组件的数据)。这反而是内联模板的缺点,就是作用域比较难理解,如果不是非常特殊的场景,建议不要轻易使用内联模板。

    实际报错:

    vue.2.6.11.js:634 [Vue warn]: Property or method "message" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
    
    

    无法识别父组件中的message变量

    动态组件

    Vue.js提供了一个特殊的元素<component>用来动态地挂载不同的组件,使用is特性来选择要挂载的组件。

    <body>
        <div id="app">
            <component :is="currentView"></component>
    
            <button @click="handleChangeView('A')">切换到A</button>
            <button @click="handleChangeView('B')">切换到B</button>
            <button @click="handleChangeView('C')">切换到C</button>
            <button @click="handleChangeView('D')">切换到D</button>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('global-component', {
                template: '<div>组件D</div>'
            });
    
            var app = new Vue({
                el: '#app',
                data: {
                    currentView: 'comA'
                },
                components: {
                    comA: {
                        template: '<div>组件A</div>'
                    },
                    comB: {
                        template: '<div>组件B</div>'
                    },
                    comC: {
                        template: '<div>组件C</div>'
                    }
                },
                methods: {
                    handleChangeView: function (component) {
                        if (component === "D") {
                            this.currentView = 'global-component'; 
                        } else {
                            this.currentView = 'com' + component;
                        }
                    }
                }
            });
        </script>
    </body>
    
    • <component :is="currentView"></component>

    异步组件

    使用的组件足够多时,是时候考虑下性能问题了,因为一开始把所有的组件都加载是没必要的一笔开销。好在Vue.js允许将组件定义为一个工厂函数,动态地解析组件。Vue.js只在组件需要渲染时触发工厂函数,并且把结果缓存起来,用于后面的再次渲染。

    <body>
        <div id="app">
            <my-component></my-component>
        </div>
        <script src="../lib/vue.2.6.11.js"></script>
        <script>
            Vue.component('my-component', function (resolve, reject) {
                setTimeout(function () {
                    resolve({
                        template: '<div>异步组件</div>'
                    });
                }, 2000)
            });
    
            var app = new Vue({
                el: '#app'
            });
        </script>
    </body>
    

    ​ 工厂函数接收一个resolve回调,在收到从服务器下载的组件定义时调用。也可以调用reject(reason)指示加载失败。这里setTimeout只是为了演示异步,具体的下载逻辑可以自己决定,比如把组件配置写成一个对象配置,通过Ajax来请求,然后调用resolve传入配置选项。

  • 相关阅读:
    (转载)SAPI 包含sphelper.h编译错误解决方案
    C++11标准的智能指针、野指针、内存泄露的理解(日后还会补充,先浅谈自己的理解)
    504. Base 7(LeetCode)
    242. Valid Anagram(LeetCode)
    169. Majority Element(LeetCode)
    100. Same Tree(LeetCode)
    171. Excel Sheet Column Number(LeetCode)
    168. Excel Sheet Column Title(LeetCode)
    122.Best Time to Buy and Sell Stock II(LeetCode)
    404. Sum of Left Leaves(LeetCode)
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/13257696.html
Copyright © 2011-2022 走看看