全局注册

使用Vue.extend(options)定义组件,参数为一个包含了被定义组选项的对象。
使用Vue.component(id,[definition])注册定义好的组件,id为该组件名称。
[definition]既可以是一个extend()返回的实例,也可以是一个包含组件选项的对象(将会自动调用extend()方法)。

使用kebab-case命名组件
var mybtn = Vue.extend({
    template: '<button class="btn btn-info">{{text}}</button>',
    data: function () {
        return { text: '使用extend自定义一个按钮' }
    }
})
/**方式一 */
Vue.component('my-btn-1', mybtn)
/**方式二 自动调用extend()*/
Vue.component('my-btn-2', {
    template: '<button class="btn btn-info mt-2">{{text}}</button>',
    data: function () {
        return {text: '使用选项对象自定义一个按钮'}
    }
})
new Vue({
    el: '#app-1'
})
<div id="app-1">
    <my-btn-1></my-btn-1>
    <br>
    <my-btn-2></my-btn-2>
</div>
注册了组件,必须要有一个根实例,如果要在根实例中使用我们的组件,那么必须在此根实例初始化之前注册

extend()中设置的data选项必须是一个函数。以上Vue实例app-1<my-btn-1|2>将被我们定义的组件所替换。

局部注册

在根实例的components选项上注册一个组件。该组件只在此根实例中使用。

new Vue({
    el: '#app-2',
    components:{
        'my-btn-1':mybtn
    }
})
//or
new Vue({
    el: '#app-3',
    components: {
        'my-btn-2': {
            template: '<button class="btn btn-info mt-2">{{text}}</button>',
            data: function () {
                return { text: '使用选项对象自定义一个按钮' }
            }
        }
    }
})

data属性

上面说过,定义组件的data选项不能是对象,必须是个函数。这是因为如果是对象,那么会给每一个组件实例返回同一个'data'对象引用,组件实例之间造成污染,这不是我们想见到的。

var data = { counter: 0 }
new Vue({
    el: '#app-3',
    components: {
        'component-3-1': {
            template:'<button @click="counter += 1" class="btn btn-info btn-sm mt-3">{{ counter }}</button>',
            //虽然它是个函数,但我们却给每个组件实例返回了同一个对象的引用
            data: function(){
                return data
            }
        },
        'component-3-2': {
            template:'<button @click="counter += 1" class="btn btn-info btn-sm mt-3">{{ counter }}</button>',
            data: function(){
                return {counter:0}
            }
        }
    }
})
<div id="app-3">
    <component-3-1></component-3-1>
    <component-3-1></component-3-1>
    <component-3-1></component-3-1>
    <br>
    <component-3-2></component-3-2>
    <component-3-2></component-3-2>
    <component-3-2></component-3-2>    
</div>

component-3-1每次返回同一个对象的引用,组件之间会互相污染。
component-3-2每次返回一个新对象,组件之间解耦。

clipboard.png

is特性

像 <ul>、<ol>、<table>、<select> 这样的元素里允许包含的元素有限制,而另一些像 <option> 这样的元素只能出现在某些特定元素的内部。
在被限制的元素中使用组件,浏览器解析时,被当成错误标签,造成错误渲染结果。
如果想要复用组件,解决方法是使用is特性在原生标签上指定一个组件。

new Vue({
    el:'#app-4',
    components: {
        'component-4':{
            template:'<tr><th scope="row">2</th><td>Jacob</td><td>Thornton</td><td>@fat</td></tr>'
        }
    }
})
<div id="app-4" style="width:300px">
    <table class="table">
        <thead class="thead-dark">
            <tr>
                <th scope="col">#</th>
                <th scope="col">First</th>
                <th scope="col">Last</th>
                <th scope="col">Handle</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th scope="row">1</th>
                <td>Mark</td>
                <td>Otto</td>
                <td>@mdo</td>
            </tr>
            <component-4></component-4>
            <tr is="component-4"></tr>
        </tbody>
    </table>
</div>

clipboard.png

直接使用<component-4>,整个模板都被丢出<table>
使用is正确解析。

另外is也被用于动态的切换组件,见组件(6):动态组件


yanniecheung
70 声望6 粉丝