天天看點

vue基礎篇---vue元件《2》

定義全局元件

我們通過Vue的component方法來定義一個全局元件。

<div id="app">
    <!--使用定義好的全局元件-->
    <counter></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
    // 定義全局元件,兩個參數:1,元件名稱。2,元件參數
    Vue.component("counter",{
        template:'<button v-on:click="count++">你點了我 {{ count }} 次,我記住了.</button>',
        data(){
            return {
                count:0
            }
        }
    })
    var app = new Vue({
        el:"#app"
    })
</script>      
  • 元件其實也是一個Vue執行個體,是以它在定義時也會接收:data、methods、生命周期函數等
  • 不同的是元件不會與頁面的元素綁定,否則就無法複用了,是以沒有el屬性。
  • 但是元件渲染需要html模闆,是以增加了template屬性,值就是HTML模闆
  • 全局元件定義完畢,任何vue執行個體都可以直接在HTML中通過元件名稱來使用元件了。
  • data的定義方式比較特殊,必須是一個函數。 

元件的複用

定義好的元件,可以任意複用多次:

<div id="app">
    <!--使用定義好的全局元件-->
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>      

你會發現每個元件互不幹擾,都有自己的count值。怎麼實作的?

當我們定義這個

<counter>

元件時,它的data 并不是像這樣直接提供一個對象:

data: {
  count: 0
}      

取而代之的是,一個元件的 data 選項必須是一個函數,是以每個執行個體可以維護一份被傳回對象的獨立的拷貝:

data: function () {
  return {
    count: 0
  }
}      

如果 Vue 沒有這條規則,點選一個按鈕就會影響到其它所有執行個體!

局部注冊

一旦全局注冊,就意味着即便以後你不再使用這個元件,它依然會随着Vue的加載而加載。

是以,對于一些并不頻繁使用的元件,我們會采用局部注冊。

我們先在外部定義一個對象,結構與建立元件時傳遞的第二個參數一緻:

const counter = {
    template:'<button v-on:click="count++">你點了我 {{ count }} 次,我記住了.</button>',
    data(){
        return {
            count:0
        }
    }
};      

然後在Vue中使用它:

var app = new Vue({
    el:"#app",
    components:{
        counter:counter // 将定義的對象注冊為元件
    }
})      
  • components就是目前vue對象子元件集合。
    • 其key就是子元件名稱
    • 其值就是元件對象的屬性
  • 效果與剛才的全局注冊是類似的,不同的是,這個counter元件隻能在目前的Vue執行個體中使用 

元件通信

父向子傳遞props

比如我們有一個子元件:

Vue.component("introduce",{
    // 直接使用props接收到的屬性來渲染頁面
    template:'<h3>{{title}}</h3>',
    props:[title] // 通過props來接收一個父元件傳遞的屬性
})      
  • 這個子元件中要使用title屬性渲染頁面,但是自己并沒有title屬性
  • 通過props來接收父元件屬性,名為title 

父元件使用子元件,同時傳遞title屬性:

<div id="app">
    <h1>打個招呼:</h1>
    <!--使用子元件,同時傳遞title屬性-->
    <introduce title="大家好,我是虎哥"/>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
    Vue.component("introduce",{
        // 直接使用props接收到的屬性來渲染頁面
        template:'<h1>{{title}}</h1>',
        props:['title'] // 通過props來接收一個父元件傳遞的屬性
    })
    var app = new Vue({
        el:"#app"
    })
</script>      

傳遞複雜資料

我們定義一個子元件:

const myList = {
    template:'\
        <ul>\
            <li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>\
        </ul>\
        ',
    props:{ // 通過props來接收父元件傳遞來的屬性
        items:{// 這裡定義items屬性
            type:Array,// 要求必須是Array類型
            default:[] // 如果父元件沒有傳,那麼給定預設值是[]
        }
    }
}      
  • 這個子元件可以對 items 進行疊代,并輸出到頁面。
  • 但是元件中并未定義items屬性。
  • 通過props來定義需要從父元件中接收的屬性
    • items:是要接收的屬性名稱
    • type:限定父元件傳遞來的必須是數組,否則報錯
    • default:預設值 

我們在父元件中使用它:

<div id="app">
    <h2>傳智播客已開設如下課程:</h2>
    <!-- 使用子元件的同時,傳遞屬性,這裡使用了v-bind,指向了父元件自己的屬性lessons -->
    <my-list :items="lessons"/>
</div>      
var app = new Vue({
    el:"#app",
    components:{
        myList // 當key和value一樣時,可以隻寫一個
    },
    data:{
        lessons:[
            {id:1, name: 'java'},
            {id:2, name: 'php'},
            {id:3, name: 'ios'},
        ]
    }
})      

子向父的通信

來看這樣的一個案例:

<div id="app">
    <h2>num: {{num}}</h2>
    <counter :count="num" @inc="increment" @dec="decrement"></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
    Vue.component("counter", {
        template:'\
            <div>\
                <button @click="plus">加</button>  \
                <button @click="reduce">減</button>  \
            </div>',
        props:['count'],
        methods:{
            plus(){
                this.$emit("inc");
            },
            reduce(){
                this.$emit("dec");
            }
        }
    })

    var app = new Vue({
        el:"#app",
        data:{
            num:0
        },
        methods:{ // 父元件中定義操作num的方法
            increment(){
                this.num++;
            },
            decrement(){
                this.num--;
            }
        }
    })


</script>      
  • vue提供了一個内置的this.$emit函數,用來調用父元件綁定的函數