1. 程式人生 > >Vue元件以及元件之間的通訊

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>
{{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

 

一、元件的註冊

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