VUE實例的生命周期和VUE提供的鈎子方法
鈎子方法就是事先給你准備好的方法,但是需要你自己實現
盜官方的圖,真香!
紅色框子里的英文就代表我們可以使用鈎子方法的方法名
注意事項:
不要在選項屬性或回調上使用箭頭函數,比如 created: () => console.log(this.a)
或 vm.$watch('a', newValue => this.myMethod())
。因為箭頭函數並沒有 this
,this
會作為變量一直向上級詞法作用域查找,直至找到為止,經常導致 Uncaught TypeError: Cannot read property of undefined
或 Uncaught TypeError: this.myMethod is not a function
之類的錯誤。
new Vue({
el:"#app",
data:{},
methods:{},
created:function(){
console.log("執行created方法")
},
mounted:function(){
console.log("執行mounted方法")
}
})
組件
組件是可以復用的VUE實例
組件的命名規范,單詞首字母大寫(例如ButtonCounter)或者全小寫使用連接線(例如button-counter)
最簡單的使用方法,注釋解決了一個坑
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->組件</title> </head> <body> <div id="app"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> </div> <script> //定義一個組件 此方式代表全局注冊 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">你點一下我就加一,現在是:{{ count }}</button>' }); new Vue({el:"#app"});<!--實例要寫在組件定義之后--> </script> </body> </html>
每用一次組件都會創建一個新的實例,互不干擾
這是因為data的選項是一個必須是一個函數,因此每個實例可以維護一份被返回對象的獨立拷貝
data: function () {
return {
count: 0
}
}
如下寫法導致多個實例共用一個對象值
data: {
count: 0
}
通過 Prop 向子組件傳遞數據
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->組件</title> </head> <body> <div id="app"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> <blog-post title="這就是傳過來的值"></blog-post> <blog-post v-for="item in posts" v-bind:title="item.title"></blog-post> </div> <script> //定義一個組件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">你點一下我就加一,現在是:{{ count }}</button>' }); //定義一個可以傳值的組件 Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3>' }) new Vue({el:"#app", data:{ posts: [ { id: 1, title: 'My journey with Vue' }, { id: 2, title: 'Blogging with Vue' }, { id: 3, title: 'Why Vue is so fun' } ] } } );<!--實例要寫在組件定義之后--> </script> </body> </html>
注意事項:每個組件必須只有一個根元素,假如上面的模板(template)這樣定義就會報錯
Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3><h2>{{ title }}</h2>' })
解決的方法就是把所有的標簽都放在同一個父標簽中
Vue.component('blog-post', { props: ['title'], template: '<div><h3>{{ title }}</h3><h2>{{ title }}</h2></div>' })
重構一下組件了,讓它變成接受一個單獨的 post
prop
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->組件</title> </head> <body> <div id="app"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> <!-- <blog-post title="這就是傳過來的值"></blog-post> <blog-post v-for="item in posts" v-bind:title="item.title"></blog-post>--> <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:post="post" ></blog-post> </div> <script> //定義一個組件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">你點一下我就加一,現在是:{{ count }}</button>' }); //定義一個可以傳值的組件 /*Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3><h2>{{ title }}</h2>' })*/ /* Vue.component('blog-post', { props: ['title'], template: '<div><h3>{{ title }}</h3><h2>{{ title }}</h2></div>' })*/ Vue.component('blog-post', { props: ['post'], template: "<div class='blog-post'><h3>{{ post.title }}</h3><div v-html='post.content'></div></div> " }) new Vue({el:"#app", data:{ posts: [ { id: 1, title: 'My journey with Vue',content:"第一個文章內容" }, { id: 2, title: 'Blogging with Vue',content:"第二個文章內容" }, { id: 3, title: 'Why Vue is so fun' ,content:"第三個文章內容"} ] } } );<!--實例要寫在組件定義之后--> </script> </body> </html>
監聽子組件事件
組件定義時綁定v-on:click='$emit(`enlarge-text`)'
組件使用時綁定v-on:enlarge-text="postFontSize += 0.1"
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->組件</title> </head> <body> <div id="blog-posts-events-demo" > <div :style="{ fontSize: postFontSize + 'em' }"> <blog-post v-on:enlarge-text="postFontSize += 0.1" v-for="post in posts" v-bind:key="post.id" v-bind:post="post" ></blog-post> </div> </div> <script> Vue.component('blog-post', { props: ['post'], template: " <div class='blog-post'> <h3>{{ post.title }}</h3> <button v-on:click='$emit(`enlarge-text`)'> Enlarge text </button> <div v-html='post.content'></div></div>" }) new Vue({ el: '#blog-posts-events-demo', data: { posts: [ { id: 1, title: 'My journey with Vue',content:"第一個文章內容" }, { id: 2, title: 'Blogging with Vue',content:"第二個文章內容" }, { id: 3, title: 'Why Vue is so fun' ,content:"第三個文章內容"}], postFontSize: 1 } }) <!--實例要寫在組件定義之后--> </script> </body> </html>
插槽
插槽的定義
Vue.component('alert-box', { template:"<div class='demo-alert-box'> <strong>Error!</strong> <slot></slot> </div>" })
<slot></slot>就的代表組件插入的位置
<alert-box> Something bad happened. </alert-box>
局部注冊
上面所有使用Vue.component()方式注冊的組件都是全局的,全局注冊所有的組件意味着即便你已經不再使用一個組件了,它仍然會被包含在你最終的構建結果中。這造成了用戶下載的 JavaScript 的無謂的增加。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->組件</title> </head> <body> <div id="app"> <component-a></component-a> <component-b></component-b> </div> <div id="app1"> <component-a></component-a> <component-b></component-b> </div> <script> var ComponentA ={ template:"<strong>ComponentA!</strong>" }; var ComponentB ={ template:"<strong>ComponentB!</strong>" }; new Vue({ el: '#app', components: { 'component-a': ComponentA, 'component-b': ComponentB } }) </script> </body> </html>
上面的代碼對中id為app1的div是無法使用那兩個組件的,但也不會報錯
注意局部注冊的組件在其子組件中不可用。
var ComponentB ={ template:"<strong>ComponentB! <component-a></component-a></strong>" };
如果你想向上面一樣在B組件里使用A組件,你需要這樣寫
var ComponentB ={ components:{ 'component-a': ComponentA }, template:"<strong>ComponentB! <component-a></component-a></strong>" };
prop
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="../js/vue.js"></script> <title>Assembly--->組件</title> </head> <body> <div id="app"> <blog-post title="靜態傳入" ></blog-post> <!-- 數值的傳入需要使用v-bind進行綁定--> <blog-post v-bind:likes="123"></blog-post> <!--傳遞一個boolean isPublished要變為is-published--> <blog-post v-bind:is-published="true"></blog-post> <!--傳遞一個對象--> <blog-post v-bind:author="{ name: 'Veronica', company: 'Veridian Dynamics' }" ></blog-post> <!--傳遞一個數組--> <blog-post v-bind:comment-ids="[123, 456, 789]"></blog-post> <!-- 動態賦予一個變量的值 --> <div v-for="post in items"> <blog-post v-bind:title="post"></blog-post> </div> <!-- <blog-post v-bind:title="post.title + ' by ' + post.author.name"></blog-post>--> </div> <script> Vue.component('blog-post', { // 在 JavaScript 中是 camelCase 的 props: { title: String, likes: Number, isPublished: Boolean, commentIds: Array, author: Object, callback: Function, contactsPromise: Promise // or any other constructor }, template: '<h3>{{title}}--{{likes}}-->{{isPublished}}-->{{author}}-->{{commentIds}}</h3>' }) new Vue({ el: '#app', data:{ items:["天雁","孤歐","風鶴","血雕","斗鷹"] } }) </script> </body> </html>