Vue 组件注册

Vue 组件注册

我们先来看一下什么是组件:
Vue.js的组件就是提高重用性的,让代码可复用。
下面是一个Vue组件的示例,现在可以不用理解下面的代码:

<div id="app">
    <hi></hi>
</div>
<script>
    Vue.component("hi", {
        data: function () {
            return {
                hello: "你好!"
            }
        },
        template: "<div>{{hello}}</div>"
    });
    var app = new Vue({
        el: "#app",
    })
</script>

<hi>就是自定义的标签,一个自定义的标签就是一个组件。最后<hi>标签会被替换为template中定义的模板内容。
渲染结果为:

<div id="app">
    <div>你好!</div>
</div>

可以将组件进行任意次的复用:

<div id="app">
   <hi></hi>
   <hi></hi>
   <hi></hi>
</div>

渲染结果为:

<div id="app">
    <div>你好!</div>
    <div>你好!</div>
    <div>你好!</div>
</div>

了解组件的内容,先从组件的注册开始。

(1)组件的注册

组件需要注册之后才可以使用。有两种组件注册的方法:全局注册和局部注册。

1.全局注册

全局注册的组件在注册之后可以用在任何新建的Vue根实例的模板中,比如:

<div id="app">
    <test1></test1>
    <test2></test2>
    <test3></test3>
    <test4></test4>
</div>
<script>
    Vue.component('test1', {});
    Vue.component('test2', {});
    Vue.component('test3', {});
    Vue.component('test4', {});
    var app = new Vue({
        el: "#app",
    })
</script>

这几个组件在各自内部也都可以相互使用。

2.局部注册

可以在Vue实例中使用components选项来注册局部组件,注册后的组件只有在该实例作用域下有效。

<div id="app">
    <hello></hello>
</div>
<script>
    var aaa= {
        template: `
            <div>你好!</div>
        `
    };
    var app = new Vue({
        el: "#app",
        components: {
            'hello':aaa
        }
    })
</script>

渲染的结果为:

<div id="app">
        <div>你好!</div>
</div>

对于components属性,属性名就是自定义组件的名字,属性值就是这个组件的选项对象。

3.组件名

在注册组件的时候,需要给组件一个名字,以便以后使用。

    Vue.component('test', {
     //some code
    });

这里的"test"就是组件的名字,作为Vue.component的第一个参数。
定义组件名的方式有两种:
A.短横线分割命名(kebab-case)

Vue.component('my-component-name', { 
//some code
});

当使用短横线分割命名法来定义一个组件的时候,在引用这个组件的时候也必须使用短横线分割命名的名字,即<my-component-name>。
B.驼峰式命名(PascalCase)

Vue.component('MyComponentName', { 
//some code
});

当使用驼峰式命名法来定义一个组件的时候,在引用这个组件的时候使用两种命名法命名的名字都可以,<my-component-name>或者<MyComponentName>。

但是要注意的是,HTML 中的特性名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着,使用 DOM 中的模板时(非字符串模板),camelCase (驼峰命名法) 的命名需要使用其等价的 kebab-case (短横线分隔命名) 命名。

也就是说,在非字符串模板中使用时,只有短横线分割命名是有效的。

下面我们来看一下,什么是字符串模板,什么是非字符串模板:

字符串模板指的是在组件选项里用 template:"" 指定的模板,比如:
<div id="app">
    <an></an>
</div>
<script>
    Vue.component('an', {
       template: `
        <div>
           <TestCan>
           </TestCan>
        </div>
       `
    });
    Vue.component('TestCan', {
        template: `
        <div>
          你好!
        </div>
       `
    });
    var app = new Vue({
        el: "#app",
    })
</script>

在注册组件<an>的时候,在template中使用了 <TestCan>,这种写法是没有问题的,最后可以成功渲染:

<div id="app">
    <div>
        <div>你好!</div>
    </div>
</div>
非字符串模板,也就是DOM模板,指的是原本就写在页面上的内容,能被浏览器识别的html结构,会一加载就被浏览器渲染。

主要是下面这两种情况:
A.利用template标签来实现内容的填充,最终通过id挂载到template上面:

<div id="app">
    <test></test>
</div>
<template id="template">
    <div>
    <TestCan></TestCan>
    <h1>我是非字符串模板!</h1>
    </div>
</template>
<script>
    Vue.component('TestCan', {
        template: `
        <div>
          你好!
        </div>
       `
    });
    Vue.component("test", {
        template: "#template"
    });
    var app = new Vue({
        el: "#app",
    })
</script>

在<template id=“template”></template>中使用驼峰命名法,是会报错的:

HTML 中的特性名是大小写不敏感的,浏览器会把所有TestCan解释为testcan,会认为testcan组件没有注册。
换用短横线分隔命名法就可以正确渲染:

<div id="app">
    <test></test>
</div>
<template id="template">
    <div>
    <test-can></test-can>
    <h1>我是非字符串模板!</h1>
    </div>
</template>
<script>
    Vue.component('TestCan', {
        template: `
        <div>
          你好!
        </div>
       `
    });
    Vue.component("test", {
        template: "#template"
    });
    var app = new Vue({
        el: "#app",
    })
</script>

渲染结果为:

<div id="app">
    <div>
        <div>
            你好!
        </div>
        <h1>我是非字符串模板!</h1>
    </div>
</div>

B.内联模板:在使用组件时,给组件标签使用inline-template特性,组件就会把它的内容当作模板,例如:

<div id="app">
    <test inline-template>
        <div>
            <test-can></test-can>
            <div>{{msg}}</div>
        </div>
    </test>
</div>
<script>
    Vue.component('TestCan', {
        template: `
        <div>
          你好!
        </div>
       `
    });
    Vue.component("test", {
        data: function () {
            return {
                msg: "我来自子组件!"
            }
        }
    });
    var app = new Vue({
        el: "#app",
    })
</script>

对于上面的代码,有以下几点需要注意:
1.内联模板可以使用子组件中声名的数据(这里是msg)
2.只能有一个根元素,如上面代码,把节点包裹在一个<div>中
3.驼峰式命名的组件名称要换用短横线分隔命名的名称

另外一种模板的写法

改变script中的type变为type=“text/x-template”,并且给它id,最终挂载到template中。

放在type=”text/x-template”中的内容将不会被浏览器解析,不被执行,不被显示。
因为不会被浏览器解析,所以不会涉及到浏览器会把所有大写字符解释为小写字符的问题。所以,这样的模板写法,采用驼峰式命名也可以正确渲染:

<div id="app">
    <test></test>
</div>
<script type="text/x-template" id="template">
    <div>
        <TestCan></TestCan>
        <h1>我是非字符串模板!</h1>
    </div>
</script>

<script>
    Vue.component('TestCan', {
        template: `
        <div>
          你好!
        </div>
       `
    });
    Vue.component("test", {
        template: "#template"
    });
    var app = new Vue({
        el: "#app",
    })
</script>
<div id="app">
    <test></test>
</div>
<script type="text/x-template" id="template">
    <div>
        <test-can></test-can>
        <h1>我是非字符串模板!</h1>
    </div>
</script>

<script>
    Vue.component('TestCan', {
        template: `
        <div>
          你好!
        </div>
       `
    });
    Vue.component("test", {
        template: "#template"
    });
    var app = new Vue({
        el: "#app",
    })
</script>

两种写法都可以正确渲染:

<div id="app">
    <div>
        <div>
            你好!
        </div>
        <h1>我是非字符串模板!</h1>
    </div>
</div>
(2)组件选项中的template

在上面注册组件的时候,用到了template,template用来定义组件的内容。
下面代码中,最后自定义标签<hi>会被替换为template中定义的模板内容。

<div id="app">
    <hi></hi>
</div>
<script>
    Vue.component("hi", {
        template: "<div>你好!</div>"
    });
    var app = new Vue({
        el: "#app",
    })
</script>

渲染结果为:

<div id="app">
    <div>你好!</div>
</div>

要注意的是,template的DOM结构必须被一个元素包含,直接在template中写文字是不会被渲染的。

只能有单个根元素

如下编写模板会报错:

    Vue.component('test', {
            template: `
                <div>1</div>
                <div>2</div>
        `
    });

因为在模板中出现了两个根元素,两个<div>。
为了解决这个问题,可以将它们包裹在一个父元素中。

    Vue.component('test', {
        template: `
                <div>
                  <div>1</div>
                  <div>2</div>
                </div>
        `
    });
(3)组件选项中的data必须是一个函数

组件是可复用的Vue实例,它们可以与new Vue接收相同的选项,例如:data、computed、watch、methods以及生命周期钩子函数等。但是像el这样的根实例特有的选项是不能接收的。对于data选项需要注意的是:
一个组件的 data 选项必须是一个函数:

<div id="app">
    <hi></hi>
</div>
<script>
    Vue.component("hi", {
        data: function () {
            return {
                hello: "你好!"
            }
        },
        template: "<div>{{hello}}</div>"
    });
    var app = new Vue({
        el: "#app",
    })
</script>

在javascript中对象是引用关系,如果return的对象引用了一个外部对象,那么这个对象就是共享的,任何一方的修改都会同步:

<div id="app">
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>
<script>
    var data = {
        count: 0
    };
    Vue.component("counter", {
        data: function () {
            return data
        },
        template: "<button v-on:click='count++'>{{count}}</button>"
    });
    var app = new Vue({
        el: "#app",
    })
</script>

点击任何一个按钮都会使得count增加1。
修改一下代码,组件返回一个新的data对象,每个实例就有一个返回对象的独立的拷贝:

<div id="app">
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>
<script>
    Vue.component("counter", {
        data: function () {
            return  {
                count: 0
            }
        },
        template: "<button v-on:click='count++'>{{count}}</button>"
    });
    var app = new Vue({
        el: "#app",
    })
</script>

这样三个按钮就互不影响,相互独立了。

参考:
1.Vue.js官方文档
2.《Vue.js实战》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值