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传入配置选项。

  • 相关阅读:
    php错误抑制符
    php执行运算符
    php中一个经典的!==的用法
    php实现简单验证码的功能
    jquery是什么
    php连接符
    php与java语法的区别
    考雅思策略
    php魔术常量
    PHP中数据类型转换的三种方式
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/13257696.html
Copyright © 2011-2022 走看看