Vue之組件

組件
     1.組件(component)是Vue最強大的功能,組件能夠擴展HTML元素,封裝可重用的代碼,在較高層面上,組件是自定義元素,Vue編譯器爲它添加新特性,在有些狀況下,組件也能夠是原生的HTML形式,以is特性擴展。
     2.使用組件
         1.全局組件:Vue.component
        <div id="box">
                <hello></hello>
        </div>
    //vue組件component。全局組件,能夠在多個定義的Vue根元素裏面使用,狀態沒辦法在狀態中進行共享,name不能在VM的根元素data中定義,data若是要在組件中使用就必須設置成一個function而不是對象
    Vue.component('hello',{
        template:`
        <div>
            我是hello全局組件,實現data裏面的對象通訊,data中的name爲{{name}}
            <hellochild></hellochild>
        </div>`,
        data:function(){//data必需要設置成方法才能讓狀態共享
            return{
                name:'xiaowang',
            }
        },
        //也能夠寫子組件
        components:{
            'hellochild':{
                template:``,
            }
        },
        methods: {
        },
    })
         2.局部組件
        <div id="box">
                <hello3></hello3>
        </div>
    var vm = new Vue({
        el:'#box',
        data:{
            myText:'',
        },
        components:{
            'hello3':{
                template:`
                <div>我是屬性的hello3局部組件,</div>`,
            },
        }
    });
         3.data必須是函數
         4.注意點
            1.自定義組件須要有一個root element
            2.父子組件的data沒法共享,
            3.組件有data,methods,computed。。可是data必須是一個函數
        5.組件意味着協同工做,一般父子組件會是這樣的關係,組件A在它的模板中使用了組件B,它們之間必然須要通訊,父組件要給子組件傳遞數據,子組件須要將組件內發生的事情告知父組件。而後,在一個良好定義的接口中將父子組件解耦是很重要的,這保證了各個組件在相對獨立的空間書寫和理解,也大幅度的提升了組件的可維護性和重用性。在Vue中,父子組件通訊可總結爲,props down,events up,父組件經過props給子組件傳遞信息,而子組件則經過events給父組件報告數據
     3.prop
        <div id="box">
            <!-- 設置子組件的屬性,經過使用props來進行通訊 -->
            <hello2 name="sarah" age="100"></hello2>
        </div>
    var vm = new Vue({
        el:'#box',
        data:{
            name:'xiaolv',
        },
        //局部組件,只能在vm #box這個根元素中使用
        components:{
            'hello2':{
                template:`
                <div>
                    我是屬性name爲{{name}},age爲{{age}}的hello2局部組件,用來實現子組件的屬性綁定
                </div>`,
            //組件中屬性的通訊,
            props:['name','age'],
            },
        },
        
    });
        1.prop傳遞數據,props:["name"]
        2.單向數據流,防止組件無心間改變了父組件的狀態。
             注意:不要在子組件修改prop-單向數據流
        3.prop驗證 props:{name:Number},咱們能夠爲組件props指定驗證規格,若是傳入的數據不符合規格,Vue會發出警告,當組件給其餘人使用時,這頗有用,要指定驗證規格,要使用對象形式,而不能使用字符串數組。
                props:{
                    name:String,
                    age:Number
                },
     4.自定義事件
        1.使用$on(eventname)監聽事件
          使用$emit(eventname)觸發事件
    <div id="box">
        <!-- 設置父組件監控子組件的方法名event -->
        <hello @event="handleParentClick"></hello>
    </div>
    Vue.component('hello',{
        //在template這個key值能夠寫HTML的DOM結構,用es6的字符串模板,chrome是支持的,若是不支持的瀏覽器能夠用wellpack
        template:`
        <div>
            我是hello全局組件,實現data裏面的對象通訊,data中的name爲{{name}}
            <ul>實現data對象中dataList的屬性遍歷
                <li v-for="data in dataList">{{data}}</li>
                <li><button @click="handleclick">用event和emit實現父子組件通訊click事件</button></li>
            </ul>
        </div>`,
        data:function(){//必需要設置成方法才能讓狀態共享
            return{
                name:'xiaowang',
                dataList:['aaa','bbb','ccc'],
            }
        },
        methods: {
            handleclick(){
                //子組件事件分發,使用父組件方法中的函數名event,由於未來一個子組件可能會有不少的觸發事件,因此要對應每個方法名,也能夠給父元素的方法傳送數據,逗號後面跟上須要傳送的數據。父元素中加入形參data就行
                this.$emit('event',this.name);
            },
        },
    })
    var vm = new Vue({
        el:'#box',
        data:{
            name:'xiaolv',
        },
        methods:{
            //父組件監聽子組件hello的事件
            handleParentClick(data){
                console.log('parentClick' + data);
            },
        },
        
    });
         2.v-model父子通訊
            props:["value"];
            this.$emit("input","***");
              <input v-model="something"/> 實際上等於下面語法糖  <input v-bind:value="something" v-on:input="something = $event.target.value"/> 
    <!-- 用v-model父子通訊, -->
    <div id="box2">
        <!-- 用v-model來實現父子組件的通訊,將會更簡單,在父元素data中添加myText的字符串屬性 -->
        <p>用v-model來實現父子組件的通訊,我是父組件data中的myText值{{myText}},能夠接收來自子組件hello3的input中的值{{myText}}</p>
        <hello3 v-model="myText"></hello3>
    </div>
    //用來實現v-model父組件和子組件的通訊
    var vm2 = new Vue({
        el:'#box2',
        data:{
            myText:'',
        },
        components:{
            //用來實現v-model的父子組件通訊
            'hello3':{
                template:`
                <div>
                    //我是屬性的hello3局部組件,用來實現v-model父組件和子組件的通訊
                    <input type="text" :value="value" @input="handleInput"/>
                </div>`,
                //若是要實現父子組件通訊,這裏的值必須用value,它會將父組件中data中的myText值傳遞給子組件的中的input中:value的值,若是要實現子組件對父組件的傳遞信息則要添加@input="handleInput",而且在子組件的methods方法中添加handleInput方法this.$emit('input',ev.target.value);
                props:['value'],
                methods:{
                    handleInput(ev){
                        //由於監聽事件v-model實際會分紅v-on:input
                        this.$emit('input',ev.target.value);
                    }
                },
            },
        }
    });
         3.非父子通訊
            1.中央事件總線 bus = new Vue();
                注意:mounted生命週期中進行監聽
<!-- 非父子通訊,可使用子傳父,而後父傳子的方式,也可使用中央bus的方法,其實就是建立一個空Vue而後監聽事件。 -->
    <div id="box3">
        <zujian1></zujian1>
        <zujian2></zujian2>
    </div>
    //非父子通訊,用中央bus來實現,這種方式只適用於簡單的場景,若是是大型的網站的項目,咱們必需要用Vuex作狀態管理。
    var bus = new Vue();//聲明一個bus總線來調度通訊
    var vm3 = new Vue({
        el:'#box3',
        data:{
            name:'ak47',
        },
        components:{
            zujian1:{
                data:function(){
                    return{
                        name:'我是組件1的data中的name',
                    }
                },
                template:`<div>我是組件1
                <button @click="handleClick">實現非父子通訊</button>
                </div>`,
                
                methods:{
                    handleClick(){
                        //用一個Vue的空組件來發送一個xiaoming的事件
                        bus.$emit('xiaoming',this.name)
                    },
                },
            },
            zujian2:{
                template:`<div>我是組件2</div>`,
                //只要是組件都會有生命週期,當DOM組件渲染掛載完成的時候,這個聲明週期就會自動的執行,聲明週期的鉤子函數,
                mounted() {
                    console.log('來自鉤子函數');
                    //用Vue的空控件bus來監聽$on 接收 xiaoming這個事件
                    bus.$on('xiaoming',function(value){
                        console.log(value);
                    });
                },
            },
        },
    });
             2.vuex狀態管理 
      非父子通訊,用中央bus來實現,這種方式只適用於簡單的場景,若是是大型的網站的項目,咱們必需要用Vuex作狀態管理
     5.插槽分發內容
        爲了讓組件能夠組合,咱們須要一種方式來混合父組件的內容與子組件本身的模板,這個過程就叫作內容分發。(或transclution,若是你熟悉angular)。Vue實現了一個內容分發API,參照了當前Web組件規範草案,使用特殊的<slot>元素做爲原始內容的插槽
            1.單個slot
            2.具名slot
    <!-- 實現內容分發,直接在組件中寫如button,這樣直接在元素中寫指令的時候,就不存在什麼父子組件傳遞信息的問題,直接在父組件調用methods方法就能夠了。 -->
    <div id="box4">
        <zujian>
            <button @click="handleClick" slot="leftBtn">leftbutton</button>
            <div>我在中間</div>
            <button @click="handleClick" slot="rightBtn">rightbutton</button>
        </zujian>
    </div>
    /* 插槽分發內容 */
    var vm4 = new Vue({
        el:'#box4',
        data:{

        },
        methods:{
            handleClick(){
                console.log(11);
            }
        },
        components:{
            zujian:{
                template:`<div>我是組件
                <slot name="leftBtn"></slot>//具名slot
                <slot></slot>//單個slot
                <slot name="rightBtn"></slot>
                </div>`,//在字符串模板中寫如slot插槽,在html中插入zujian這個元素會自動插入這個位置,能夠給插槽具名,讓對應的元素插入這個插槽
            },
        }
    });
     6.動態組件
        1.component元素,動態的綁定多個組件到它的is的屬性
        2.keep-alive,保留狀態,避免被重複渲染。
        html,body{width: 100%;height: 100%;}
        #box5{overflow-x: hidden;}
        #box5 ul{display: flex;width: 100%;height: 40px;position: fixed;left: 0;bottom: 0;}
        #box5 ul li{flex: 1;height: 40px;line-height: 40px;background: #333;list-style: none;}
        /* css動畫效果animate,確保html元素transition的name和類開始名字一致bounce */
        .bounce-enter-active{animation: bounce-in .5s;}
        .bounce-leave-active{animation: bounce-in .5s reverse;}
        @keyframes bounce-in {
            0%{transform: scale(0);}
            50%{transform: scale(1.5);}
            100%{transform: scale(1);}
        }
    <!-- 動態組件,使用component組件,在components的組件中定義好每一個組件和名字,用v-bind它的屬性is的值來自定義的來動態的實現切換頁面,在footer的點擊事件中傳入相應的值是和子組件的名字一一對應的。 每次點擊都會從新建立頁面和銷燬前一個頁面,可是若是頁面內容中有須要保持內容的信息存在,好比在home頁中有一個輸入框文本按鈕,須要用到keep-alive來實現內容的緩存-->
    <div id="box5">
        <keep-alive>
            <!-- 能夠呈現的組件添加一個過渡效果,這裏實現的是多組件的過渡效果 -->
            <transition name="bounce" mode="out-in">
                <component :is="current"></component>
            </transition>
        </keep-alive>
        <footer>
            <ul>
                <li @click="handleClick('home')">home</li>
                <li  @click="handleClick('list')">list</li>
                <li  @click="handleClick('shopcart')">shopcart</li>
            </ul>
        </footer>
    </div>
    /* 動態組件 */
    var vm5 = new Vue({
        el:'#box5',
        data:{
            current:'home',
        },
        components:{
            home:{
                template:`<div>我是home<input type="text"/>
                </div>`,
            },
            list:{
                template:`<div>我是list</div>`,
            },
            shopcart:{
                template:`<div>我是shopcart</div>`,
            },
        },
        methods:{
            handleClick(data){
                this.current = data;
            },
        },
    })
相關文章
相關標籤/搜索