zoukankan      html  css  js  c++  java
  • vue.js基础知识篇(6):组件详解

    第11章:组件详解

     组件是Vue.js最推崇也最强大的功能之一,核心目标是可重用性。

    我们把组件代码按照template、style、script的拆分方式,放置到对应的.vue文件中。

    1.注册

    Vue.js的组件注册分为全局注册和局部注册。

    全局注册使用Vue.component方法。第一个参数是组件名字,第二个参数是组件的构造函数,要么是function,要么是object。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
          <div id="app">
              <didi-component></didi-component>
              <en-component></en-component>
          </div>
          <script src="js/vue.js"></script>
          <script>
              //第二个参数传入object的情况
              Vue.component("didi-component",{
                  template:"<div>A custom component!</div>"
              });
              //第二个参数传入function的情况,它是一个组件构造器
              var ENcomponent=Vue.extend({
                  template:"<div>A 2rd components</div>"
              });
              //注册
              Vue.component("en-component",ENcomponent);
              //创建根实例
              new Vue({
                  el:"#app"
              })
          </script>
    </body>
    </html>

    显示效果

    局部注册,以vue实例选项components或者组件构造器即Vue.extend函数的components选项。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
        <didi-component></didi-component>
    </div>
    <script src="js/vue.js"></script>
    <script>
        var Parent=Vue.extend({
            template:"<p>这里是父组件的内容</p><br/><child></child>",
            components:{
                "child":{
                    template:"<div>我是子组件的内容</div>"
                }
            }
        })
        new Vue({
            el:"#app",
            components:{
                "didi-component":Parent
            }
        })
    </script>
    </body>
    </html>

    显示效果

    2.数据传递

    组件作为一个app(项目)的组成部分,总是要涉及到组件通信。组件通信属于数据传递的范畴,数据传递一共有3种方式:

    props、组件通信、slot。

    (1)props属性

    首先区别一下props和data和propsData。props作用于父子组件之间的数据传递,data组件或者vue实例化时经常使用,propsData用来在组件初始化后覆盖props中的属性。接下来是如何使用props属性。

    第一种方式,字面量语法

    直接在组件的html代码中传入普通的字符串,在组件内部使用props属性。注意:html不区分大小写,名字为camelCase的属性会转化为短横线隔开(kebab-case)。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
         <hello-component msg="hello"></hello-component>
        <vivian my-data="3.1415"></vivian>
    </div>
    <script src="js/vue.js"></script>
    <script>
        Vue.component("hello-component",{
            props:["msg"],
            template:"<span>{{msg}},front-end!</span>"
        });
        Vue.component("vivian",{
            props:["myData"],
            template:"<div>{{myData}}</div>",
            replace:true
        })
        new Vue({
            el:"#app"
        })
    </script>
    </body>
    </html>

    第二种,动态语法

    下面的例子从父组件向子组件传递属性,每当父组件的数据变化时,该变化也会传导给子组件。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div id="app">
            <vivi-props></vivi-props>
        </div>
        <script src="js/vue.js"></script>
        <script>
            var Child=Vue.extend({
                props:["viviProps"],
                //传给子组件的属性名称
                template:"<div>{{viviProps}}</div>",
                //既然在props属性上定义了,那么就可以在模板里使用了
                replace:true
            });
            var Parent=Vue.extend({
                template:"<p>我是父组件的内容</p><br/><child :vivi-props='hello'></child>",
                data:function(){
                  return {"hello":"hello"}
                },
                //动态绑定的属性的值由父组件的data来定义
                components:{
                    "child":Child
                }
            })
            new Vue({
                el:"#app",
                components:{
                    "vivi-props":Parent
                }
            });
        </script>
    </body>
    </html>

    第三种方式,使用.sync和.once修饰符。

    默认或者使用.once修饰符是父组件到子组件的单向绑定。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div id="app">
            <input type="text" v-model="info.name"/>
            <child v-bind:msg.once="info"></child>
            <!--把根实例的info数据属性传递给子组件child的msg属性-->
        </div>
        <script src="js/vue.js"></script>
        <script>
            new Vue({
                el:"#app",
                data:{
                    info:{
                        name:"顺风车"
                    }
                },
                components:{
                    "child":{
                        props:["msg"],
                        template:"<div>{{msg.name}}</div>"
                    }
                }
            })
        </script>
    </body>
    </html>

    .sync修饰符能做到双向绑定。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
        父组件:
        <input v-model="val"><br/>
        子组件:
        <test :test.sync="val"></test>
    </div>
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                val: 1
            },
            components: {
                "test": {
                    props: ['test'],
                    template: "<input v-model='test'/>"
                }
            }
        });
    </script>
    </body>
    </html>

    显示结果

    第4种方式,prop验证。

     我们把自己的组件给别人使用,那么要求使用者能够根据prop提供的对象正确使用。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
        父组件:
        <input v-model="val"><br/>
        子组件:
        <test :test="val"></test>
    </div>
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                val: 1
            },
            components:{
                test:{
                    props: {
                        test: {
                            twoWay: true
                        }
                        //我们希望组件的使用者通过双向绑定来使用这个组件。
                    },
                    //把根实例的val属性传递给test属性。
                    template: "<input v-model='test'/>"
                }
            }
        });
    </script>
    </body>
    </html>

    我们看到这个代码 <test :test="val"></test> 会抛出错误如下:

    那么正确的使用应该是如下,加上.sync修饰词,以满足twoWay:true的要求。

    第5种方式,prop转换函数,coerce函数。可以理解为prop属性值的过滤器。

    (2)组件通信

    尽管this.$parent和this.$children(属性)可以访问父/子组件的数据,根实例的后代可以通过this.$root访问根实例,但这种方式应该尽量避免。

    首先,因为父子组件紧密的耦合,只看父组件却很难理解父组件的状态,因为它能被任意的修改。再次,子组件要使用父组件的数据,应当避免直接依赖,尽量显式的使用props属性。

    我们的方案是通过作用域传递事件。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
       <template id="child-template">
           <input v-model="msg">
           <button v-on:click="notify">Dispatch Event</button>
           <!--子组件绑定了notify函数-->
       </template>
        <div id="events-example">
            <p>Message:{{messages|json}}</p>
            <child></child>
        </div>
    </div>
    <script src="js/vue.js"></script>
    <script>
        Vue.component("child",{
            template:"#child-template",
            data:function(){
                return {msg:"hello"}
            },
            methods:{
                notify:function(){
                    if(this.msg.trim()){
                        this.$dispatch("child-msg",this.msg);
                        this.msg="";
                    }
                    //notify函数的功能是把msg属性的值dispatch到child-msg事件上,它会沿着父作用域的链冒泡
                }
            }
        });
        var parent=new Vue({
            el:"#events-example",
            data:{
                messages:[]
            },
            events:{
                "child-msg":function(msg){
                    this.messages.push(msg);
                }
                //接收到child-msg事件后,那么执行push方法
            }
        })
        var vm = new Vue({
            el: '#app'
        });
    </script>
    </body>
    </html>

    接下来是在子组件v-on监听,更加简洁的代码。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
        <template id="child-template">
            <input v-model="msg">
            <button v-on:click="notify">Dispatch Event</button>
            <!--子组件绑定了notify函数-->
        </template>
        <div id="events-example">
            <p>Message:{{messages|json}}</p>
            <child v-on:child-msg="handleIt"></child>
        </div>
    </div>
    <script src="js/vue.js"></script>
    <script>
        Vue.component("child",{
            template:"#child-template",
            data:function(){
                return {msg:"hello"}
            },
            methods:{
                notify:function(){
                    if(this.msg.trim()){
                        this.$dispatch("child-msg",this.msg);
                        this.msg="";
                  
                    //notify函数的功能是把msg属性的值dispatch,触发child-msg事件,它会沿着父作用域的链冒泡
                }
            }
        });
        var parent=new Vue({
            el:"#events-example",
            data:{
                messages:[]
            },
            //改动后的代码
            methods:{
                handleIt:function(msg){
                    this.messages.push(msg);
                }
            }
        })
        var vm = new Vue({
            el: '#app'
        });
    </script>
    </body>
    </html>

    有时js中直接访问子组件,可用v-ref为子组件指定一个索引ID。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
        <div id="events-example">
            <p>Message:{{messages|json}}</p>
            <button @click="handleIt">打印msg字符串儿</button>
            <!--点击按钮,那么执行handleIt方法-->
            <child v-ref:id1></child>
        </div>
    </div>
    <script src="js/vue.js"></script>
    <script>
        Vue.component("child",{
            template:"<div>{{msg}}</div>",
            data:function(){
                return {msg:"hello"}
            }
        });
        var parent=new Vue({
            el:"#events-example",
            data:{
                messages:[]
            },
            //改动后的代码
            methods:{
                handleIt:function(){
                    console.log(this.$refs.id1.msg);
                    //那么就可以直接通过id名访问到子组件的属性了
                }
            }
        })
        var vm = new Vue({
            el: '#app'
        });
    </script>
    </body>
    </html>
    
    </body>
    </html>

    (3)slot分发内容

    组合组件时,内容分发API是非常有用的机制。

    <vivi>
       <vivi-header></vivi-header>
       <vivi-footer></vivi-footer>
    </vivi>

    首先,明确分发内容的作用域。

    <child v-on:child-msg="handleIt">{{msg}}</child>

    msg绑定到父组件的数据还是子组件的数据里?答案是父组件。因为父组件模板的内容在父组件的作用域里编译,子组件模板的内容在子组件的作用域里编译。

    所以对于分发内容(接下来就知道什么是分发内容了), 在父组件内容里编译。

    接下来看,单个slot。

    当子组件模板里只有一个没有任何修饰的Slot,那么父组件的整个内容将插入到slot的挂载点并替换掉它。

    单个slot的DEMO:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <template id="viviTemplate">
            <div>
                <h1>这里是vivi组件的内容</h1>
                <slot>
                    如果没有分发内容,则显示我
                </slot>
                <!--回退内容,当宿主元素为空没有内容插入时-->
            </div>
        </template>
    <div id="app">
        <vivi-component>
            <p>这里是原始内容</p>
            <p>这里是更多的原始内容</p>
            <!--很明显,这里的p标签的作用域并不是vivi-component的内容,而是它的父组件的内容-->
        </vivi-component>
    </div>
    <script src="js/vue.js"></script>
    <script>
        Vue.component("vivi-component",{
            template:"#viviTemplate",
        })
        var vm = new Vue({
            el: '#app'
        });
    </script>
    </body>
    </html>
    
    </body>
    </html>

    显示效果:

    接下来看,命名的slot的用法。

    <slot>元素可使用name配置如何分发内容。仍然可以有一个匿名的slot,作为找不到匹配内容片段的回退容器。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <template id="multiTemplate">
            <div>
                <slot name="one"></slot>
                <slot></slot>
                <slot name="two"></slot>
            </div>
        </template>
        <div id="app">
           <multi-insertion>
              
               <p slot="one">One</p>
               <!--对应name值为one的被分发内容-->
               <p slot="two">Two</p>
               <!--对应name值为two的被分发的内容-->
               <p>Default A</p>
               <p slot="three"></p>
               <!--对应默认的被分发的内容-->
              
           </multi-insertion>
        </div>
    <script src="js/vue.js"></script>
    <script>
        Vue.component("multi-insertion",{
            template:"#multiTemplate",
        })
        var vm = new Vue({
            el: '#app'
        });
    </script>
    </body>
    </html>
    
    </body>
    </html>

    显示结果:

    最后分析一下,源码。

    SLOT的源码如下:

    var slot = {
    
        priority: SLOT,//优先级
        params: ['name'],//
       //bind方法的功能是绑定指令
        bind: function bind() {
          
          var name = this.params.name || 'default';
         
          var content = this.vm._slotContents && this.vm._slotContents[name];
         
          if (!content || !content.hasChildNodes()) {
     
            this.fallback();
          } else {
            this.compile(content.cloneNode(true), this.vm._context, this.vm);
        
          }
        },
    
        compile: function compile(content, context, host) {
        //
          if (content && context) {
          
    if (this.el.hasChildNodes() && content.childNodes.length === 1 && content.childNodes[0].nodeType === 1 && //对v-if指令的处理,略。 content.childNodes[0].hasAttribute('v-if')) { var elseBlock = document.createElement('template'); elseBlock.setAttribute('v-else', ''); elseBlock.innerHTML = this.el.innerHTML; elseBlock._context = this.vm; content.appendChild(elseBlock); } var scope = host ? host._scope : this._scope; this.unlink = context.$compile(content, host, scope, this._frag); } if (content) { replace(this.el, content); } else { remove(this.el); } // }, fallback: function fallback() { this.compile(extractContent(this.el, true), this.vm); //把元素的内容抽出来,然后编译 }, unbind: function unbind() { if (this.unlink) { this.unlink(); } // } };

      先来看bind方法。这里的this指的是<slot>指令,通过name获取到分发的内容,比如 <p slot="one">One</p> 。有分发的内容,那么就添加到slot指令挂载的元素。没有就把slot指令所在元素删除掉。

    3.混合

    使用混合对象(把选项分离出来,然后组合进组件的选项中)。好处是方便分布复用功能。

    第一,简单的混合例子:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
       <div id="app">
         <vivi-component></vivi-component>
       </div>
    <script src="js/vue.js"></script>
    <script>
        var myMixin={
            created:function(){
                this.hello();
            },
            methods:{
                hello:function(){
                    console.log("hello from mixin!");
                }
            }
        };
        //myMixin要放在使用之前定义哦。顺序问题很重要。
        new Vue({
            el:"#app",
            components:{
                "vivi-component":{
                    template:"<h1>hello ,vivian!</h1>",
                    mixins:[myMixin]
                }
            }
        })
    
    
    </script>
    </body>.
    </html>

    第二,当混合对象与组件有同名选项时,以适当的策略合并。同名钩子函数被并入一个数组中,因而都会被调用。而且顺序是,混合的钩子函数比组件的钩子函数更早被调用。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>混合对象</title>
    </head>
    <body>
    <div id="app">
        <vivi-component></vivi-component>
    </div>
    <script src="js/vue.js"></script>
    <script>
        var myMixin={
            created:function(){
                this.hello();
            },
            methods:{
                hello:function(){
                    console.log("hello from mixin!");
                }
            }
        };
        new Vue({
            el:"#app",
            components:{
                "vivi-component":{
                    template:"<h1>hello ,vivian!</h1>",
    
                    created:function(){
                        console.log("组件内容被调用");
                    },
                    mixins:[myMixin]
                }
            }
        })
    
    
    </script>
    </body>.
    </html>

    显示两个钩子函数都有被调用哦.

    第三,methods、components、directives都是对象选项,合并时如果键冲突,那么组件的选项优先。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
    
    </div>
    <script src="js/vue.js"></script>
    <script>
        var myMixin={
            methods:{
                foo:function(){
                    console.log("foo");
                },
                conflicting:function(){
                    console.log("from mixin");
                }
            }
    
        };
        var component=Vue.extend({
            mixins:[myMixin],
            template:"<h1>hello,vivi</h1>",
            methods:{
                bar:function(){
                    console.log("bar");
                },
                conflicting:function(){
                    console.log("来自组件本身");
                }
            }
        });
        var vm=new component();
        vm.foo();//因为混合才有foo方法,所以打印foo
        vm.bar();//因为只有组件才有bar方法,所以打印bar
        vm.conflicting();//因为这个方法混合对象和组件都有,根据组件优先的原则,所以打印“来自组件本身”。
    
    </script>
    </body>.
    </html>

    调用的打印结果如下

    第四,混合全局注册要慎用。会影响之后创建的所有vue实例。大多数情况下,只用于自定义选项。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
    
    </div>
    <script src="js/vue.js"></script>
    <script>
        Vue.mixin({
            created:function(){
              var myOption=this.$options.myOption;
               if(myOption){
                   console.log(myOption);
               }
            }
           }
        );
        var component=Vue.extend({
            template:"<h1>hello,vivi!</h1>"
        });
        new Vue({
            el:"#app",
            components:{
                "my-component":component
            },
            myOption:"hello"
        })
    </script>
    </body>
    </html>

    4.动态组件

    多个组件可以使用同一个挂载点,然后动态的在它们之间切换。

    第一,动态组件的简单例子

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
       <div id="app">
           <input type="radio" id="one" value="dev" v-model="currentView"/>
           <label for="one">开发</label>
           <br/>
           <input type="radio" id="two" value="painting" v-model="currentView"/>
           <label for="two">画画</label>
           <br/>
           <input type="radio" id="three" value="travel" v-model="currentView"/>
           <label for="three">旅游</label>
           <br/>
           <template id="dev">
               <div>开发</div>
           </template>
           <template id="painting">
               <div>画画</div>
           </template>
           <template id="travel">
               <div>旅游</div>
           </template>
           <component :is="currentView">
               <!--组件在vm.currentView变化时改变-->
           </component>
       </div>
       <script src="js/vue.js"></script>
       <script>
        var dev=Vue.extend({
            template:"#dev",
            replace:"true"
        });
        var painting=Vue.extend({
            template:"#painting",
            replace:"true"
        });
        var travel=Vue.extend({
            template:"#travel",
            replace:true
        });
        var vm=new Vue({
            el:"#app",
            data:{
                currentView:"dev"
            },
            components:{
                dev:dev,
                painting:painting,
                travel:travel
            }
        })
       </script>
    </body>
    </html>

    显示效果

    第二,

    keep-alive特性会让组件重复创建时通过缓存来获取,从而快速创建,当然是提高了视图的性能。

    使用的语法如下:

    <component :is="currentView" keep-alive>
               <!--组件在vm.currentView变化时改变-->
           </component>

    从源码中可以窥得一二:

    第三,activate钩子函数。

    它是组件切入前执行。可用来控制组件切换的时长。activate钩子只作用于动态组件切换或者静态组件初始化渲染的过程。不用于使用实例方法手动插入的过程。

    完整的代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
        <input type="radio" id="one" value="dev" v-model="currentView"/>
        <label for="one">开发</label>
        <br/>
        <input type="radio" id="two" value="painting" v-model="currentView"/>
        <label for="two">画画</label>
        <br/>
        <input type="radio" id="three" value="travel" v-model="currentView"/>
        <label for="three">旅游</label>
        <br/>
        <template id="dev">
            <div>开发</div>
        </template>
        <template id="painting">
            <div>画画</div>
        </template>
        <template id="travel">
            <div>旅游</div>
        </template>
        <component :is="currentView" transition="fade" transition-mode="out-in">
            <!--改变的代码,先淡出再淡入-->
        </component>
    </div>
    <style>
        .fade-transition{
            transition:opacity .3s ease;
        }
        .fade-enter,.fade-leave{
            opacity:0;
        }
    </style>
    <script src="js/vue.js"></script>
    <script>
        var dev=Vue.extend({
            template:"#dev",
            replace:"true",
            activate:function(done){
               var self=this;
               console.log("在组件替换前打印");
    
                setTimeout(function(){
                    console.log("计时器中的代码");
                    done();
                },5000);
                //延时5秒
            }
        });
        var painting=Vue.extend({
            template:"#painting",
            replace:"true"
        });
        var travel=Vue.extend({
            template:"#travel",
            replace:true
        });
        var vm=new Vue({
            el:"#app",
            data:{
                currentView:"dev"
            },
            components:{
                dev:dev,
                painting:painting,
                travel:travel
            }
        })
    </script>
    </body>
    </html>

    可以看到在组件被插入前,它会执行activate函数,做了延时5秒的操作。

    第四,transition-mode特性。用于指定两个动态组件之间如何过渡。

    代码如下:

     <component :is="currentView" transition="fade" transition-mode="out-in">
            <!--改变的代码,先淡出再淡入-->
        </component>
    <style>
        .fade-transition{
            transition:opacity .3s ease;
        }
        .fade-enter,.fade-leave{
            opacity:0;
        }
    </style>

    完整的有渐进效果的DEMO:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
        <input type="radio" id="one" value="dev" v-model="currentView"/>
        <label for="one">开发</label>
        <br/>
        <input type="radio" id="two" value="painting" v-model="currentView"/>
        <label for="two">画画</label>
        <br/>
        <input type="radio" id="three" value="travel" v-model="currentView"/>
        <label for="three">旅游</label>
        <br/>
        <template id="dev">
            <div>开发</div>
        </template>
        <template id="painting">
            <div>画画</div>
        </template>
        <template id="travel">
            <div>旅游</div>
        </template>
        <component :is="currentView" transition="fade" transition-mode="out-in">
            <!--改变的代码,先淡出再淡入-->
        </component>
    </div>
    <style>
        .fade-transition{
            transition:opacity .3s ease;
        }
        .fade-enter,.fade-leave{
            opacity:0;
        }
    </style>
    <script src="js/vue.js"></script>
    <script>
        var dev=Vue.extend({
            template:"#dev",
            replace:"true"
        });
        var painting=Vue.extend({
            template:"#painting",
            replace:"true"
        });
        var travel=Vue.extend({
            template:"#travel",
            replace:true
        });
        var vm=new Vue({
            el:"#app",
            data:{
                currentView:"dev"
            },
            components:{
                dev:dev,
                painting:painting,
                travel:travel
            }
        })
    </script>
    </body>
    </html>

    5.生命周期

     

    在vue.js中,实例化vue之前,它们以HTML的文本形式保存在文本编辑器中。当实例化后将经历,创建、编译、销毁3个主要阶段。

    生命周期钩子:

    (1)init:

    在实例开始初始化时同步调用,此时数据观测、事件和watcher都尚未初始化。

    (2)created:

    在实例创建之后同步调用,此时实例已经结束解析选项,也就是数据绑定、计算属性、方法、watcher/事件回调已经建立。但是还没有开始DOM编译,$el还不存在。

    (3)beforeCompile:

    在编译开始前调用。

    (4)compiled:

    编译结束后调用,此时所有的指令已生效,因而数据的变化将触发DOM更新。但是不担保$el已插入文档。

    (5)ready:

    在编译结束和$el第一次插入文档之后调用,注意必须有vue插入(比如vm.$appendTo())才能触发ready钩子的。

    (6)attached:

    vm.$el插入DOM时调用。必须是由指令或者实例方法(比如$appendTo())插入,直接操作$vm.el不会触发钩子。

    (7)detached

    在vm.$el从DOM中删除时调用。必须是由指令或者实例方法删除,直接操作vm.$el不会触发这个钩子。

    (8)beforeDestory:

    在开始销毁实例时调用,此时实例仍然有功能。

    (9)destroyed:

    在实例销毁之后调用。

    6.开发组件

    使用.vue文件实现组件化。具体的代码执行请参看vue.js工具篇的webpack。

    <template>
        <div class="header">
            <h1> {{ title }} </h1>
        </div>
    </template>
    
    <script>
        export default {
            data: function () {
                return {
                    title: '我是頭部'
                }
            }
        }
    </script>
    
    <style>
        .header {
            color: red;
        }
    </style>
  • 相关阅读:
    java maven 操作 收集的一些命令
    Java多线程,线程交替执行
    java类同时引用父类和接口的成员变量,需要指明是父类的还是接口的
    artTemplate 模板使用
    Dubbo 只注册,只订阅
    Tomcat灵活配置多项目,多端口,多域名,多虚拟目录
    CentOS7.2 安装nginx-1.10.3
    CentOS7.2 安装zookeeper3.4.9
    CentOS7.2 安装Redis3.2.8
    CentOS7.2 切换成iptables规则
  • 原文地址:https://www.cnblogs.com/chenmeng2062/p/7067256.html
Copyright © 2011-2022 走看看