Vue元件以及元件之間的通訊
一、元件的註冊
1、 全域性元件註冊
1. 註冊基本語法Vue.component
Vue.component("my_header", { template: `<div><h1>{{title}}</h1></div>`, data() { return { title: "這是頭部" } } });View Code
2. 第一個引數"my_header":元件名稱
3. 第二個引數{}:配置資訊
4. 配置資訊裡面必須要有template,它的值是這個元件的html程式碼
5. 還可以有data、methods等引數,不同的是data不是物件了,而是函式,return返回的值,在template中可以獲取並使用
函式詳寫是 data:function(){}; ES6中可以直接簡寫 data(){return },其他函式一樣可以簡寫省略 :function
6. Vue裡面有的引數,元件裡面多數也有,但是有一些引數是元件不能有的,比如el引數,所有元件都是Vue可複用的例項
7. 全域性元件,所有app都可以使用
8. demo
<body> <div id="app"> <my_header></my_header> </div> <hr> <div id="app2"> <my_header></my_header> </div> <script> Vue.component("my_header", { template: `<div><h1>View Code{{title}}</h1></div>`, data() { return { title: "這是頭部" } } }); const app = new Vue({ el: "#app", }); const app2 = new Vue({ el: "#app2" }) </script> </body>
2、區域性元件註冊
1. 在某個app下注冊元件,其他app不能使用
2. 基本語句:某個app內使用引數components: {元件名稱1: 配置資訊1, 元件名稱2: 配置資訊2}
3. demo
<body> <div id="app"> <my_com></my_com> <my_com></my_com> </div> <script> // 元件配置資訊(物件) let my_com_config = { template: `<div><h1>這是區域性元件</h1></div>` }; const app = new Vue({ el: "#app", components: { // 元件名稱: 配置資訊 my_com: my_com_config } }); </script> </body>View Code
3、子元件的註冊
1. 在某個元件內,也可以使用components使用另一個元件
2. 子元件需要這個元件的template程式碼內使用
3. demo
<body> <div id="app"> <my_com></my_com> </div> <script> let child_config = { template: `<div><h2>我是子元件</h2></div>` }; let my_com_config = { // 在元件的程式碼裡面引用它的子元件 template: `<div> <h1>這是一個元件</h1> <child></child> </div>`, // 在某個元件內部也可以定義的它的子元件 components: { child: child_config } }; const app = new Vue({ el: "#app", components: { my_com: my_com_config } }) </script> </body>View Code
二、元件之間的通訊
1、父子元件之間的通訊
1. 在父元件的配置資訊template中引用子元件,給子元件設定一個屬性,值是父元件data的值
2. 在子元件中配置一個props引數(陣列),裡面是那個屬性名
3. 然後在子元件的template程式碼中就可以直接使用這個屬性獲取到父元件傳過來的值
4. demo
<body> <div id="app"> <my_com></my_com> </div> <script> let child_config = { template: `<div> <h2>我是子元件</h2> <p>父親對我說:{{father_say}}</p> </div>`, props: ["father_say"] }; let my_com_config = { template: `<div> <h1>這是一個元件</h1> <child :father_say="f_say"></child> </div>`, components: { child: child_config }, data(){ return { f_say: "好好學習" } } }; const app = new Vue({ el: "#app", components: { my_com: my_com_config } }) </script> </body>View Code
2、子父元件之間的通訊
1. 子元件向父元件傳資料,需要提交一個事件
2. 在一個事件中通過this.$emit("事件名稱", "要傳的值")提交另一個事件給父親
3. 在父元件中繫結子元件提交過來的事件,建立一個方法處理這個事件
4. data函式接收子元件提交過來的資料
5. demo
<body> <div id="app"> <my_com></my_com> </div> <script> let child_config = { // 設定一個click事件,通過click事件向父親提交一個事件son_say和資料 template: `<div> <h2>我是一個子元件</h2> <button @click="my_click">點擊向父親說話</button> </div>`, methods: { my_click() { // 向父親說話 // 子元件提交事件 this.$emit("son_say", "我會好好學習的") } } }; let my_com_config = { // 父元件接收子元件提交的事件son_say,並給這個事件設定一個處理方法my_son_say // 處理後的資料就可以使用了{{say}} template: `<div> <h1>這是一個元件</h1> <child @son_say="my_son_say"></child> <p>兒子跟我說:{{say}}</p> </div> `, components:{ child: child_config }, data(){ return { say: "" } }, // 接收子元件傳來的資料data,並賦值給say,在程式碼中展示出來 methods: { my_son_say: function (data) { this.say = data } } }; const app = new Vue({ el: "#app", components: { my_com: my_com_config } }) </script> </body>View Code
3、非父子元件之間的通訊
1. 定義一個Vue例項作為兩個元件之間通訊的橋樑
2. 其中一個元件向中間排程器提交事件:Event.$emit("事件名稱", data)
3. 另一個元件要監聽中間排程器裡的事件:Event.$on("事件的名稱", function(data){
4. 注意this的問題:函式裡面的this是最近的呼叫者,外面的this才是這個元件
5. demo
<body> <div id="app"> <ming></ming> <hong></hong> </div> <script> // 這個Vue例項不用傳資料,只是用於兩個元件之間通訊的橋樑 // 一個元件給這個例項提交事件,另一個元件在這個例項裡監聽這個事件 let other = new Vue(); let ming_config = { template: `<div> <h1>我是明哥</h1> <button @click="my_click">給小紅打電話</button> </div>`, methods: { my_click: function() { // 給小紅打電話,說晚上等我,一起嗨 // 兩個元件之間沒有關係(不是父子),需要通過一個Vue物件進行通訊 // 給other物件提交事件 other.$emit("call", "晚上等我,一起嗨") } } }; let hong_config = { template: `<div> <h1>我是紅姐</h1> <p>明哥勇猛地跟涐說:{{ming_say}}</p> </div>`, data(){ return { ming_say: "" } }, // 鉤子方法,元件載入完成後會執行這個方法 mounted(){ // 和$emit是一對的,$emit是提交事件,$on是監聽$emit提交的事件 // 第一個引數是監聽的事件名稱,第二個引數是監聽到後要執行的回撥函式 let that = this; // 這個this是hong這個元件 other.$on("call", function(data){ // data是ming傳過來的資料,裡面的this是other的 that.ming_say = data; }) } }; const app = new Vue({ el: "#app", components: { ming: ming_config, hong: hong_config } }) </script> </body>View Code
三、混合和插槽
1、混合
1. 當兩個元件複用共用的程式碼塊時
2. 定義公共的程式碼塊
3. 複用語法:mixins: [變數名]
4. demo
<body> <div id="app"> <com1></com1> <com2></com2> </div> <script> // 定義公用程式碼 let base = { data() { return { is_show: false } }, methods: { show_text: function(){ this.is_show = true; }, hide_text(){ this.is_show = false; } } }; let com1 = { template: `<div> <button @click="show_text">點選顯示文字</button> <button @click="hide_text">點選隱藏文字</button> <div v-show="is_show">威猛的明哥出現了</div> </div>`, // 繼承公用程式碼 mixins: [base], // 還可以修改繼承過來的程式碼 data(){ return { is_show: true } } }; let com2 = { template: `<div> <button v-on="{mouseenter: show_text, mouseleave: hide_text}">滑鼠移入顯示文字,移出隱藏</button> <div v-show="is_show">威猛的明哥出現了</div> </div>`, // 繼承程式碼 mixins: [base] }; const app = new Vue({ el: "#app", components: { com1: com1, com2: com2, } }) </script> </body>View Code
2、 插槽
1. 把元件的template定義在html裡面
2. 在script中通過id找到這段template
3. template程式碼內定義slot插槽,並使用name屬性區分不同的插槽資訊
4. 使用元件的時候通過slot,可以給元件新增上不同的內容
5. 生成的元件程式碼中不會有template標籤
6. demo
<body> <div id="app"> <com> <h3 slot="title">Python</h3> <p slot="brief">從入門到精通</p> </com> <com> <h3 slot="title">Mysql</h3> <p slot="brief">從刪庫到跑路</p> </com> </div> <!--元件的template還可以單獨寫出來--> <template id="my_com"> <div> <h1>這是一個元件</h1> <!--用slot定義插槽--> <slot name="title"></slot> <slot name="brief"></slot> <hr> </div> </template> <script> let com = { // 找到template模板 template: "#my_com" }; const app = new Vue({ el: "#app", components: { com: com } }) </script> </body>View Code
一、元件的註冊
1、 全域性元件註冊
1. 註冊基本語法Vue.component
Vue.component("my_header", { template: `<div><h1>{{title}}</h1></div>`, data() { return { title: "這是頭部" } } });View Code
2. 第一個引數"my_header":元件名稱
3. 第二個引數{}:配置資訊
4. 配置資訊裡面必須要有template,它的值是這個元件的html程式碼
5. 還可以有data、methods等引數,不同的是data不是物件了,而是函式,return返回的值,在template中可以獲取並使用
函式詳寫是 data:function(){}; ES6中可以直接簡寫 data(){return },其他函式一樣可以簡寫省略 :function
6. Vue裡面有的引數,元件裡面多數也有,但是有一些引數是元件不能有的,比如el引數,所有元件都是Vue可複用的例項
7. 全域性元件,所有app都可以使用
8. demo
<body> <div id="app"> <my_header></my_header> </div> <hr> <div id="app2"> <my_header></my_header> </div> <script> Vue.component("my_header", { template: `<div><h1>{{title}}</h1></div>`, data() { return { title: "這是頭部" } } }); const app = new Vue({ el: "#app", }); const app2 = new Vue({ el: "#app2" }) </script> </body>View Code
2、區域性元件註冊
1. 在某個app下注冊元件,其他app不能使用
2. 基本語句:某個app內使用引數components: {元件名稱1: 配置資訊1, 元件名稱2: 配置資訊2}
3. demo
<body> <div id="app"> <my_com></my_com> <my_com></my_com> </div> <script> // 元件配置資訊(物件) let my_com_config = { template: `<div><h1>這是區域性元件</h1></div>` }; const app = new Vue({ el: "#app", components: { // 元件名稱: 配置資訊 my_com: my_com_config } }); </script> </body>View Code
3、子元件的註冊
1. 在某個元件內,也可以使用components使用另一個元件
2. 子元件需要這個元件的template程式碼內使用
3. demo
<body> <div id="app"> <my_com></my_com> </div> <script> let child_config = { template: `<div><h2>我是子元件</h2></div>` }; let my_com_config = { // 在元件的程式碼裡面引用它的子元件 template: `<div> <h1>這是一個元件</h1> <child></child> </div>`, // 在某個元件內部也可以定義的它的子元件 components: { child: child_config } }; const app = new Vue({ el: "#app", components: { my_com: my_com_config } }) </script> </body>View Code
二、元件之間的通訊
1、父子元件之間的通訊
1. 在父元件的配置資訊template中引用子元件,給子元件設定一個屬性,值是父元件data的值
2. 在子元件中配置一個props引數(陣列),裡面是那個屬性名
3. 然後在子元件的template程式碼中就可以直接使用這個屬性獲取到父元件傳過來的值
4. demo
<body> <div id="app"> <my_com></my_com> </div> <script> let child_config = { template: `<div> <h2>我是子元件</h2> <p>父親對我說:{{father_say}}</p> </div>`, props: ["father_say"] }; let my_com_config = { template: `<div> <h1>這是一個元件</h1> <child :father_say="f_say"></child> </div>`, components: { child: child_config }, data(){ return { f_say: "好好學習" } } }; const app = new Vue({ el: "#app", components: { my_com: my_com_config } }) </script> </body>View Code
2、子父元件之間的通訊
1. 子元件向父元件傳資料,需要提交一個事件
2. 在一個事件中通過this.$emit("事件名稱", "要傳的值")提交另一個事件給父親
3. 在父元件中繫結子元件提交過來的事件,建立一個方法處理這個事件
4. data函式接收子元件提交過來的資料
5. demo
<body> <div id="app"> <my_com></my_com> </div> <script> let child_config = { // 設定一個click事件,通過click事件向父親提交一個事件son_say和資料 template: `<div> <h2>我是一個子元件</h2> <button @click="my_click">點擊向父親說話</button> </div>`, methods: { my_click() { // 向父親說話 // 子元件提交事件 this.$emit("son_say", "我會好好學習的") } } }; let my_com_config = { // 父元件接收子元件提交的事件son_say,並給這個事件設定一個處理方法my_son_say // 處理後的資料就可以使用了{{say}} template: `<div> <h1>這是一個元件</h1> <child @son_say="my_son_say"></child> <p>兒子跟我說:{{say}}</p> </div> `, components:{ child: child_config }, data(){ return { say: "" } }, // 接收子元件傳來的資料data,並賦值給say,在程式碼中展示出來 methods: { my_son_say: function (data) { this.say = data } } }; const app = new Vue({ el: "#app", components: { my_com: my_com_config } }) </script> </body>View Code
3、非父子元件之間的通訊
1. 定義一個Vue例項作為兩個元件之間通訊的橋樑
2. 其中一個元件向中間排程器提交事件:Event.$emit("事件名稱", data)
3. 另一個元件要監聽中間排程器裡的事件:Event.$on("事件的名稱", function(data){
4. 注意this的問題:函式裡面的this是最近的呼叫者,外面的this才是這個元件
5. demo
<body> <div id="app"> <ming></ming> <hong></hong> </div> <script> // 這個Vue例項不用傳資料,只是用於兩個元件之間通訊的橋樑 // 一個元件給這個例項提交事件,另一個元件在這個例項裡監聽這個事件 let other = new Vue(); let ming_config = { template: `<div> <h1>我是明哥</h1> <button @click="my_click">給小紅打電話</button> </div>`, methods: { my_click: function() { // 給小紅打電話,說晚上等我,一起嗨 // 兩個元件之間沒有關係(不是父子),需要通過一個Vue物件進行通訊 // 給other物件提交事件 other.$emit("call", "晚上等我,一起嗨") } } }; let hong_config = { template: `<div> <h1>我是紅姐</h1> <p>明哥勇猛地跟涐說:{{ming_say}}</p> </div>`, data(){ return { ming_say: "" } }, // 鉤子方法,元件載入完成後會執行這個方法 mounted(){ // 和$emit是一對的,$emit是提交事件,$on是監聽$emit提交的事件 // 第一個引數是監聽的事件名稱,第二個引數是監聽到後要執行的回撥函式 let that = this; // 這個this是hong這個元件 other.$on("call", function(data){ // data是ming傳過來的資料,裡面的this是other的 that.ming_say = data; }) } }; const app = new Vue({ el: "#app", components: { ming: ming_config, hong: hong_config } }) </script> </body>View Code
三、混合和插槽
1、混合
1. 當兩個元件複用共用的程式碼塊時
2. 定義公共的程式碼塊
3. 複用語法:mixins: [變數名]
4. demo
<body> <div id="app"> <com1></com1> <com2></com2> </div> <script> // 定義公用程式碼 let base = { data() { return { is_show: false } }, methods: { show_text: function(){ this.is_show = true; }, hide_text(){ this.is_show = false; } } }; let com1 = { template: `<div> <button @click="show_text">點選顯示文字</button> <button @click="hide_text">點選隱藏文字</button> <div v-show="is_show">威猛的明哥出現了</div> </div>`, // 繼承公用程式碼 mixins: [base], // 還可以修改繼承過來的程式碼 data(){ return { is_show: true } } }; let com2 = { template: `<div> <button v-on="{mouseenter: show_text, mouseleave: hide_text}">滑鼠移入顯示文字,移出隱藏</button> <div v-show="is_show">威猛的明哥出現了</div> </div>`, // 繼承程式碼 mixins: [base] }; const app = new Vue({ el: "#app", components: { com1: com1, com2: com2, } }) </script> </body>View Code
2、 插槽
1. 把元件的template定義在html裡面
2. 在script中通過id找到這段template
3. template程式碼內定義slot插槽,並使用name屬性區分不同的插槽資訊
4. 使用元件的時候通過slot,可以給元件新增上不同的內容
5. 生成的元件程式碼中不會有template標籤
6. demo
<body> <div id="app"> <com> <h3 slot="title">Python</h3> <p slot="brief">從入門到精通</p> </com> <com> <h3 slot="title">Mysql</h3> <p slot="brief">從刪庫到跑路</p> </com> </div> <!--元件的template還可以單獨寫出來--> <template id="my_com"> <div> <h1>這是一個元件</h1> <!--用slot定義插槽--> <slot name="title"></slot> <slot name="brief"></slot> <hr> </div> </template> <script> let com = { // 找到template模板 template: "#my_com" }; const app = new Vue({ el: "#app", components: { com: com } }) </script> </body>View Code