組件(Component)是 Vue.js最強大的功能之一。組件能夠擴展 HTML元素,封裝可重用的代碼組件是自定義元素(對象)。vue
官方推薦組件標籤名是使用-
鏈接的組合詞,例如:<my-hello></my-hello>
。緩存
使用這種方式建立組件首先須要使用Vue.extend()
建立一個組件構造器,而後使用Vue.component(標籤名,組件構造器)
,根據組件構造器來建立組件。app
//1.建立構造器 var MyComponent=Vue.extend({ template:'<h3>Hello World</h3>' }); //2.建立組件 Vue.component('my-hello',MyComponent); //3.使用組件 <div id="app"> <my-hello></my-hello> </div>
這種建立組件的方式比較麻煩,使用的較少。dom
使用Vue.component(標籤名,組件模板)
,根據組件構造器來建立組件。函數
//1.建立組件 Vue.component('my-world', { template: '<h2>hello vue.js</h2>' }); //2.使用組件 <div id="app"> <my-world></my-world> </div>
組件分爲全局組件和局部組件。this
使用Vue.component()
建立的組件都是全局組件。這樣的組件在任何組件內都能使用。上面咱們建立就是全局組件。code
局部組件通常都是定義在實例的選項中,稱爲實例的子組件。相應的,實例也被稱爲父組件。component
//1.定義組件 new Vue({ el: '#app', components: { dawei: { template: '<h2>my name is dawei</h2>' } } }); //2.使用組件 <div id="app"> <dawei></dawei> </div>
不少時候咱們的template
模板中須要存放不少標籤內容,這樣的話寫起來會很麻煩。這時候咱們可使用template
標籤。對象
用法以下:事件
<template id="wbs"> //使用template標籤 <div> <h2>hello {{msg}}</h2> <ul> <li v-for="value in arr"> {{value}} </li> </ul> </div> </template> new Vue({ el: '#app', components: { 'my-dawei': { template: '#wbs', //選擇template標籤 data() { return { msg: 'vue.js', arr: ["a", "b", "c", "d"] } } } } });
這裏涉及到的幾個知識點得着重提一下:
template
模板中,全部的元素必須放置在一個根元素中,要否則會報錯。例子中咱們將元素放置在了<div>
標籤中。data
選項必須是一個函數類型,使用return
返回全部的數據。不少時候項目中須要在某一個地方動態的使用不一樣的組件,這時候就須要使用動態組件。
動態組件的使用須要綁定is
屬性:
<component :is="flag"></component>
簡單示例:
//點擊按鈕顯示不一樣的組件 <div id="app"> <button type="button" @click="flag='my-a'">顯示a組件</button> <button type="button" @click="flag='my-b'">顯示b組件</button> <component :is="flag"></component> //傳入flag </div> new Vue({ el: '#app', data: { flag: 'my-a' //給flag賦值 }, components: { 'my-a': { template: '<p>我是a組件</p>', }, 'my-b': { template: '<p>我是b組件</p>' } } });
使用keep-alive
組件緩存非活動組件,能夠保留狀態,避免從新渲染,默認每次都會銷燬非活動組件並從新建立。
使用範例:
<keep-alive> <component :is="flag"></component> </keep-alive> <div id="app"> <button type="button" @click="flag='my-x'">x</button> <button type="button" @click="flag='my-y'">y</button> <keep-alive> <component :is="flag"></component> </keep-alive> </div> new Vue({ el: '#app', data: { flag: 'my-x' }, components: { 'my-x': { template: '<p>{{x}}</p>', data() { return { x: Math.random() } } }, 'my-y': { template: '<p>{{y}}</p>', data() { return { y: Math.random() } } } } });
這樣的話,第一次產生的隨機數就會被緩存,再次切換的時候也不會發生改變。
在一個組件內部定義另外一個組件,那麼這對組件稱爲父子組件。子組件只能在父組件內部使用。默認狀況下,每一個組件實例的做用域是獨立的,子組件沒法訪問父組件中的數據,一樣,父組件也沒法訪問子組件中的數據。
<div id="app"> <my-a></my-a> <!-- 父組件 --> </div> <template id="a"> <div> <p>{{msg}}</p> <my-b></my-b> <!-- 在父組件中調用子組件 --> </div> </template> <template id="b"> <div> <p>{{mydata}}</p> </div> </template> <script> new Vue({ //根組件 el: '#app', components: { //子組件寫在components選項中 "my-a": { //b組件的父組件 template: "#a", data() { return { msg: '我是父組件', } }, components: { //子組件寫在父組件的components選項中 "my-b": { template: "#b", data() { return { mydata: "我是子組件" } } } } } } }); </script>
步驟:
改進上面的例子:
<div id="app"> <my-a></my-a> </div> <template id="a"> <div> <p>{{msg}}</p> <p>這是要傳遞給子組件的值:{{myname}}</p> <my-b :name="myname"></my-b> <!-- 綁定子組件想要獲取的數據 --> </div> </template> <template id="b"> <div> <p>{{mydata}}</p> <p>這是父組件傳遞過來的數據:{{name}}</p> </div> </template> <script> new Vue({ el: '#app', data: {}, components: { "my-a": { template: "#a", data() { return { msg: '我是a組件', myname: '子組件b你好,我是父組件a' } }, components: { "my-b": { template: "#b", data() { return { mydata: "我是b組件" } }, props: ["name"] //子組件使用props聲明想要獲取的數據 } } } } }); </script>
步驟:
//子組件‘my-b’內部 methods:{ send(){//使用$emit()觸發一個事件,發送數據,this指當前子組件實例 this.$emit('e-world', this.senddata); } } //在調用子組件的地方監聽子組件觸發的事件,調用本身的方法獲取數據 <my-b @e-world="getData"></my-b> methods: { getData(data) { //參數是子組件傳遞過來的數據 this.revicedata = data; } }
props是單向數據綁定的,當父組件數據發生變化時,將傳遞給子組件,可是不會反過來。並且不容許子組件直接修改父組件中的數據,強制修改會報錯。
解決方案:
//使用.sync <my-b :name.sync="myname"></my-b> //子組件修改父組件傳入的值name,觸發update更新事件 this.$emit('update:name', "vuejs");
data() { return { //將要傳遞的數據放入message對象中 message: { hello: '子組件b你好,我是父組件a' } } } <my-b :message="message"></my-b> //傳遞這個對象給子組件 methods: { //在子組件內部修改這個值,這樣就會同步傳遞給父組件。 edit() { this.message.hello = "hahahahh"; } }
非父子組件間的通訊,能夠經過一個空的Vue實例做爲中央事件總線(事件中心),用它來觸發事件和監聽事件,從而實現非父子組件間的通訊。
var Event = new Vue(); //空vue實例 methods: { send() { //觸發emit事件 Event.$emit("hello", this.asmsg); } } mounted() { //在子組件的鉤子函數中監聽該事件 Event.$on('hello', data => { //獲取值 this.bsmsg = data; }) }
用來獲取組件中的原內容
var vm = new Vue({ el: '#app', components: { 'my-hello': { template: '#hello' } } }); <div id="app"> <my-hello>hello vue.js</my-hello> </div> <template id="hello"> <div> <slot>若是沒有原內容,則顯示該內容</slot> </div> </template>
若是組件標籤中沒有內容就會顯示slot中的內容,這也就是所謂的單個插槽。
還能夠對顯示的內容進行分組,這就是具名插槽,能夠操做標籤組中的內容:
<div id="app"> <my-hello> <ul slot="s1"> <li>aaa</li> <li>bbb</li> <li>ccc</li> </ul> <ol slot="s2"> <li>111</li> <li>222</li> <li>333</li> </ol> </my-hello> </div> <template id="hello"> <div> <slot name="s2"></slot> //爲插槽指定名稱 將名爲s2的內容放置在這裏 <p>hello vue.js</p> <slot name="s1"></slot> //將名爲s1的內容放置在這裏 </div> </template>
這樣,就能夠對組件中的內容實時操做。