Vue 的組件

組件

上一篇:Vue的表單輸入綁定:https://segmentfault.com/a/11...html

使用組件

註冊組件

首先咱們要建立一個實例:vue

new Vue({
    el:'.exp',
    // ......
})

要註冊一個全局組件,你可使用 Vue.component(tagName, options)。例如:segmentfault

Vue.component('my-component', {
  // 選項
})

組件在註冊以後,即可以在父實例的模塊中以自定義元素 < my-component >< /my-component > 的形式使用。要確保在初始化根實例以前註冊了組件:瀏覽器

<div class="exp">
    <my-component></my-componetn>
</div>
<script>
    Vue.component('my-component',{
        template:'<div>這是一個組件</div>'
    })
    new Vue({
        el:'.exp',
    })
</script>

渲染結果:函數

<div class="exp">
    <div>這是一個組件</div>
</div>

對於自定義標籤名,Vue.js 不強制要求遵循 W3C 規則 (小寫,而且包含一個短槓),儘管遵循這個規則比較好。this

咱們知道,在建立的實例裏面是有data數據的,其實在組件裏也能夠寫數據:spa

Vue.component('my-component'{
    templent:'<div><input type="button"></div>',
    data:function(){
        return{
            msg:'hello'
        }
    }
})

注意!組件裏的data必須是一個函數,並將屬性返回code

局部註冊

沒必要在全局註冊每一個組件。經過使用組件實例選項註冊,可使組件僅在另外一個實例/組件的做用域中可用:component

<div class="exp">
    <my-component></my-component>
</div>
<script>
    var child={
        template:'<div>這是一個局部組件</div>'
    }
    new Vue({
        el:'.exp',
        components:{
            'my-component':child
        }
    })
</script>

渲染結果和上一個例子是同樣的。htm

咱們來看看全局註冊和局部註冊的區別:

<div class="exp">
    <my-component></my-component>
</div>
<div class="exp1">
    <first></first>
</div>
<script>
    //全局註冊
    Vue.component('my-component',{
        template:'<div>這是一個全局組件</div>'
    });
    new Vue({
        el:'.exp',
    });

    // 局部註冊
    var child={
        template:'<div>這是一個局部組件</div>'
    };
    new Vue({
        el:'.exp1',
        components:{
            'first':child
        }
    });
</script>

局部註冊的組件,只能在 .exp1 內使用,拿給 .exp 是不能夠的,固然咱們把全局註冊的組件給 .exp1 ,是能夠生效的。

DOM 模板解析說明

當使用 DOM 做爲模板時 (例如,將 el 選項掛載到一個已存在的元素上), 你會受到 HTML 的一些限制,由於 Vue 只有在瀏覽器解析和標準化 HTML 後才能獲取模板內容。尤爲像這些元素 < ul >,< ol >,< table >,< select > 限制了能被它包裹的元素,而一些像 < option > 這樣的元素只能出如今某些其它元素內部。

好比:

<div class="exp">
    <table>
        <my-component></my-component>
    </table>
    
</div>

<script>
    Vue.component('my-component',{
        template:'<tr><td>1</td><td>2</td></tr>'
    });
    new Vue({
        el:'.exp',
    });
</script>

如上,這樣的寫法在DOM裏渲染時會反正錯誤:

<tr>...</tr>
<table></table>

爲了解決,就須要使用 is 屬性

<table>
    <tr is="my-component"></tr>
</table>

模板字符串

有時候咱們可能要在組件裏寫不少的標籤,若是通通像上面那樣寫的話,看起來很費勁,這時候就可使用模板字符串:

< script type="text/x-template" >< /script >

<div class="exp">
    <table>
        <tr is="my-component"></tr>
    </table>
    
</div>
<!-- 模板字符串 -->
<script type="text/x-templent" id="tmp">
    <tr>
        <td>1</td>
        <td>3</td>
        <td>4</td>
        <td>3</td>
    </tr>
</script>
<script>
    Vue.component('my-component',{
        template:'#tmp'//調用模板字符串的 id 
    });
    new Vue({
        el:'.exp',
    });
</script>

這樣寫的話就比較直觀了。

Prop

使用 prop 傳遞數據

組件實例的做用域是孤立的。這意味着不能 (也不該該) 在子組件的模板內直接引用父組件的數據。要讓子組件使用父組件的數據,咱們須要經過子組件的 props 選項。

子組件要顯式地用 props 選項聲明它期待得到的數據:

<div class="exp">
    <tk msg="hello"></tk>
</div>
<script type="text/x-templent" id="tmp">
    <div>
        <input type="button" v-on:click="alertMsg" value="彈框">
    </div>
</script>
<script>
    var tkTmp={
        template:"#tmp",
        //聲明props
        props:['msg'],
        methods:{
            alertMsg:function(){
                alert(this.msg)
            }
        }
    };
    new Vue({
        el:'.exp',
        components:{
            'tk':tkTmp
        }
    });
</script>

在上面的例子中,咱們要在子組件 tk 裏傳一個參數,就須要使用 prop 屬性.

這種方式是靜態綁定的方法,還有就是利用 v-bind 指令進行動態綁定:

<tk v-bind:msg="msg"></tk>

駝峯式命名和短橫線隔開式命名

HTML 特性是不區分大小寫的。因此,當使用的不是字符串模板,camelCased (駝峯式) 命名的 prop 須要轉換爲相對應的 kebab-case (短橫線隔開式) 命名:

ue.component('child', {
  // camelCase in JavaScript
  props: ['myMessage'],
  template: '<span>{{ myMessage }}</span>'
})
<!-- kebab-case in HTML -->
<child my-message="hello!"></child>

自定義事件

使用 v-on 綁定自定義事件

每一個 Vue 實例都實現了事件接口 (Events interface),即:

  • $on(enentName) 監聽事件

  • $emit(eventName) 觸發事件

咱們可使用 $emit 來用子組件觸發父組件的事件:

<div class="exp">
    <tk v-bind:msg="msg"></tk>
    <tk msg="HELLO WORDL" v-on:jieshou="jieshoufn"></tk>
</div>
<script type="text/x-templent" id="tmp">
    <div>
        <input type="button" v-on:click="alertMsg" value="彈框">
    </div>
</script>
<script>
    var tkTmp={
        template:"#tmp",
        props:['msg'],
        methods:{
            alertMsg:function(){
                alert(this.msg),
                this.$emit("jieshou","abc","def")
            }
        }
    };

    new Vue({
        el:'.exp',
        data:{
            msg:'hello'
        },
        components:{
            'tk':tkTmp
        },
        methods:{
            jieshoufn:function(){
                alert(2);
            }
        }
    });
</script>

當咱們點擊第二個按鈕時,就會觸發父組件內的 alert 事件。

其實咱們也能夠傳遞參數,由父組件接收:

this.$emit("jieshou","abc")

非父子組件通信

有時候兩個組件也須要通訊 (非父子關係)。在簡單的場景下,可使用一個空的 Vue 實例做爲中央事件總線:

<div class="exp">
    <tk></tk>
    <pop></pop>
</div>
<script type="text/x-templent" id="tmp">
    <div>
        <input type="button" v-on:click="alertMsg" value="彈框">
    </div>
</script>
<script>
    var bus=new Vue();//空的 vue 實例

    var tkTmp={
        template:"#tmp",
        methods:{
            alertMsg:function(){
                bus.$emit("pass",1,2)//觸發事件
            }
        }
    };
    var pop={
        template:'<div>2333</div>',
        mounted:function(){
            bus.$on("pass",function(arg1,arg2){//監聽事件
                console.log(arg1)
                console.log(arg2)
            })
        }
    }
    new Vue({
        el:'.exp',
        components:{
            'tk':tkTmp,
            'pop':pop
        }
    });
</script>

使用 Slot 分發內容

這部分官方文檔說的有點囉嗦,我這邊就合到一塊說吧。直接上個例子:

<style>
        .box{
            margin: 10px;
            width: 150px;
            border: 1px solid #ccc;
        }
        .box-header, .box-footer{
            height: 30px;
            background: sandybrown;
        }
        .box-body{
            min-height: 100px;
        }
    </style>
<body>
    <div class="exp">
        <box>
            <h2 slot="title">Slot內容分發<h2>
            <p>爲了讓組件能夠組合,咱們須要一種方式來混合父組件的內容與子組件本身的模板。這個過程被稱爲 內容分發 (或 「transclusion」 若是你熟悉 Angular)。Vue.js 實現了一個內容分發 API,參照了當前 Web 組件規範草案,使用特殊的 <slot> 元素做爲原始內容的插槽。</p>
            <p slot="foot">分發完成</p>
        </box>
    </div>

    <script type="text/x-template" id="tmp">
        <div class="box">
            <div class="box-header"><slot name="title"></slot></div>
            <div class="box-body">
                <slot></slot>
            </div>
            <div class="box-footer"><slot name="foot"></slot>
            </div>
        </div>
    </script>
    <script>
        var box={
            template:"#tmp",
        }

        new Vue({
            el:'.exp',
            components:{
                "bilibili":box
            }
        })
    </script>
</body>

< slot >被成爲插口,在組件中,咱們須要使用 slot 插口預留一個位置,以方便分發內容。如上,在放置正文內容的地方,咱們直接插入一對 slot 標籤標記出正文內容的位置。對於頁面標題和頁腳等特殊的位置,咱們就須要"具名Slot",用一個特殊的屬性 name 來配置如何分發內容。多個 slot 能夠有不一樣的名字。具名 slot 將匹配內容片斷中有對應 slot 特性的元素。

To be continue......

上一篇:Vue的表單輸入綁定:https://segmentfault.com/a/11...

相關文章
相關標籤/搜索