Vue的元件

weixin_34249678發表於2018-08-25

1、元件的概念

元件(Component)是 Vue.js 最強大的功能之一。元件可以擴充套件 HTML 元素,封裝可重用的程式碼。元件系統讓我們可以用獨立可複用的小元件來構建大型應用,幾乎任意型別的應用的介面都可以抽象為一個元件樹

2、全域性元件的註冊(所有例項都能用)

註冊一個全域性元件語法格式如下:

  • Vue.component(tagName, options)
    tagName 為元件名,options 為配置選項。
  • 註冊後,我們可以使用以下方式來呼叫元件:
    <tagName></tagName>
<div id="app">
    app<runoob></runoob>
</div>
<div id="app1">
    app1<runoob></runoob>
</div>
<script>
    // 註冊全域性元件runoob
    Vue.component('runoob', {
        template: '<h1>自定義全域性元件!</h1>'
    });
    // 建立Vue根例項
    new Vue({
        el: '#app'
    });
    new Vue({
        el:'#app1'
    })
</script>

3、區域性元件的註冊

  • 我們也可以在例項選項中註冊區域性元件,這樣元件只能在這個例項中使用
<div id="app">
    app<runoob></runoob>
</div>
<div id="app1">
    app1<runoob></runoob>
</div>
<script>
    let Child = {
        template: '<h1>自定義元件!</h1>'
    };
    // 建立Vue根例項
    new Vue({
        el: '#app',
        components: {
            // <runoob> 將只在父模板可用
            'runoob': Child
        }
    });
    new Vue({
        el:'app1'
    })
</script>

4、父子元件通訊(props)

  • prop 是父元件用來傳遞資料的一個自定義屬性。
    父元件的資料需要通過 props 把資料傳給子元件,子元件需要顯式地用 props 選項宣告 "prop":
  • 注意: prop 是單向繫結的:當父元件的屬性變化時,將傳導給子元件,但是不會反過來。
<div id="app">
    <parent></parent>
</div>
<script>
    let child = {
        template: `<div><p>這是個子元件{{name}}</p></div>`,
        // 宣告 props
        props: ["name"]
    };
    let parent = {
        //模板
        template: `<div>
                    <h1>這是個父元件</h1>
                    <child :name="username"></child>
                    </div>`,
        //註冊一個子元件
        components: {
            child: child
        },
        data() {
            return {
                username: "peiqi"
            }
        }
    };
    //建立Vue根例項
    const app = new Vue({
        el: "#app",
        //註冊一個區域性元件parent
        components: {
            parent: parent
        }
    })
</script>
  • 動態 Props
    類似於用 v-bind 繫結 HTML 特性到一個表示式,也可以用 v-bind 動態繫結 props 的值到父元件的資料中。每當父元件的資料變化時,該變化也會傳導給子元件:
<div id="app">
    <div>
      <input v-model="parentMsg">
      <br>
      <child v-bind:message="parentMsg"></child>
    </div>
</div>
 
<script>
// 註冊
Vue.component('child', {
  // 宣告 props
  props: ['message'],
  // 同樣也可以在 vm 例項中像 "this.message" 這樣使用
  template: '<span>{{ message }}</span>'
})
// 建立根例項
new Vue({
  el: '#app',
  data: {
    parentMsg: '父元件內容'
  }
})
</script>
  • 以下例項中將 v-bind 指令將 todo 傳到每一個重複的元件中:
<div id="app">
    <ol>
    <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
      </ol>
</div>
 
<script>
Vue.component('todo-item', {
  props: ['todo'],
  template: '<li>{{ todo.text }}</li>'
})
new Vue({
  el: '#app',
  data: {
    sites: [
      { text: 'Runoob' },
      { text: 'Google' },
      { text: 'Taobao' }
    ]
  }
})
</script>

5、子父元件通訊

  • 上面我們說過,props 是單向繫結的:當父元件的屬性變化時,將傳導給子元件,但是不會反過來。
  • 那麼想一下子父通訊怎麼實現呢?
    機智如你發現:給子元件繫結事件,通過$emit將事件提交(可以攜帶引數),在父元件中繫結對應事件的處理函式就可以實現子父元件的通訊了。
<div id="app">
    <parent></parent>
</div>
<script>
    // 子元件 提交一個事件 可以攜帶值
    let child = {
        template: `<div>
                        <p>這是個子元件</p>
                        <button @click="on_click">點我顯示你銀行卡餘額</button>
                    </div>`,
        methods: {
            on_click: function () {
                //提交一個事件 可以攜帶值
                this.$emit("show_balance", this.balance)
            }
        },
        data() {
            return {
                balance: 998,
            }
        }
    };
    let parent = {
        template: `<div>
                    <h1>這是個父元件</h1>
                    <child @show_balance="my_func"></child>
                      <span>{{p_balance}}</span>
                    </div>`,
        //註冊一個子元件
        components: {
            child: child
        },
        data() {
            return {
                username: "peiqi",
                p_balance: ""
            }
        },
        methods: {
            my_func: function (data) {
                this.p_balance = data
            }
        }
    };
    //建立Vue根例項
    const app = new Vue({
        //制定作用域
        el: "#app",
        //註冊一個區域性元件
        components: {
            parent: parent
        }
    })
</script>

6、非父子元件通訊

  • 非父子元件的通訊沒有辦法通過繫結事件來解決了,那就需要通過生成一箇中間Vue例項來做父子元件通訊的媒介,一個時間通過 Vue例項.on()去處理傳來的事件就可以完成兩個互不相干的元件之間的通訊了。
  • 只要思想不滑坡,方法總比問題多!!!
<div id="app">
    <alex></alex>
    <wenzhou></wenzhou>
</div>
<script>
    //生成一箇中間Vue例項用於資料傳遞
    let Event = new Vue();
    let alex = {
        template: `<div>
                    <p>Alex</p>
                    //繫結事件
                    <button @click="on_click">點我給文周降薪</button>
                    </div>`,
        methods: {
            on_click: function () {
                //提交事件、傳遞引數
                Event.$emit("alex_said", this.money)
            }
        },
        //必須是這種return的資料形式
        data() {
            return {
                money: 10000,
            }
        }
    };
    let wenzhou = {
        template: `<div>
                        <p>哪吒</p>
                        {{wz_money}}
                    </div>`,
        // 載入結束後執行的
        mounted() {
            let that = this;
            Event.$on("alex_said", function (data) {
                that.wz_money = data;
                console.log(this)
            })
        },
        data() {
            return {
                wz_money: "",
            }
        }
    };
    //建立Vue根例項
    const app = new Vue({
        //制定作用域
        el: "#app",
        //註冊兩個區域性元件
        components: {
            alex: alex,
            wenzhou: wenzhou,
        }
    })
</script>

7、mixins重複程式碼封裝,類似於django中的母板

<div id="app">
    <popup></popup>
    <tip></tip>
</div>

<script>
    let base = {
        methods: {
            on_show: function () {
                this.show = true
            },
            on_hide: function () {
                this.show = false
            }
        },
        data() {
            return {
                show: false
            }
        }
    };
    let popup = {
        template: `<div>
                        <button @click="on_show">點我顯示</button>
                        <button @click="on_hide">點我隱藏</button>
                        <p v-show="show">這是popup</p>
                   </div>`,
        mixins: [base],
        data() {
            return {
                show: true
            }
        }
    };
    let tip = {
        template: `<div>
                    <button v-on="{mouseenter: on_show, mouseleave: on_hide}">滑鼠移入提示資訊</button>
                    <p v-show="show">這是一個提示資訊</p>
                </div>`,
        mixins: [base]
    };
    const app = new Vue({
        el: "#app",
        components: {
            popup: popup,
            tip: tip,
        }
    })
</script>

8、slot插槽

<div id="app">
    <test>
        <div slot="title"> 這是一個標題</div>
        <div slot="footer">這是底部</div>
    </test>
</div>
<template id="panel-tpl">
    <div>
        <slot name="title">1</slot>
        <hr>
        <slot name="content">2</slot>
        <hr>
        <slot name="footer">3</slot>
    </div>
</template>
<script>
    let test = {
        template: "#panel-tpl"
    };
    const app = new Vue({
        el: "#app",
        components: {
            test: test
        }
    })
</script>

相關文章