vue.js——基础篇之vue组件

vue.js——基础篇之vue组件

一、什么是组件

      组件(Component)是Vue.js最强大的功能之一。组件可以扩展 HTML元素,封装可重用的代码。在较高层面上,组件是自定义元素,vue.js的编译器为它添加特殊功能,在有些情况下,组件也可以是原生HTML元素的形式,以is特性扩展。组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树。
      组件系统是Vue的另一个重要概念,因为它是一种抽象,允许使用小型、独立和通常可复用的组件构建大型应用。

组件树

在Vue里,一个组件本质上是一个拥有预定义选项的一个Vue实例。

这里写图片描述

二、组件与自定义元素的关系

1、Vue组件非常类似于自定义元素,这是因为Vue的组件语法部分参考了该规范。
2、 Web组件规范仍然处于草案阶段,并且未被所有浏览器原生实现。相比之下,Vue组件不需要任何polyfill,并且在所有支持的浏览器 (IE9 及更高版本) 之下表现一致。必要时,Vue组件也可以包装于原生自定义元素之内。
3、Vue组件提供了纯自定义元素所不具备的一些重要功能,最突出的是跨组件数据流、自定义事件通信以及构建工具集成。

三、注册全局组件

1、全局组件,所有实例都能用全局组件。

全局组件在注册之后可以用在任何新创建的Vue根实例(new Vue)的模板中。

2、注册全局组件

*注册一个全局组件语法格式如下:
       Vue.component(tagName, options)
*参数说明:
      tagName为组件名,options为配置选项。
*注册后,可使用以下方式来调用组件:
      <tagName></tagName>
*注意:
      组件在注册后,便可在父实例的模块中以自定义元素的形式使用,但要确保在初始化根实例之前注册了组件。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>注册全局组件</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <my-component></my-component>
    </div>
    <script>
        //注册全局组件
        Vue.component('my-component',{
            template:'<div>{{msg}}<input type="button" value="弹" @click="tanchu"/></div>',
            //注意:这里的data必须是一个函数,和实例中的data不一样,return返回一个对象
            data:function(){
                return {
                    msg:"Hello vue"
                };
            },
            methods:{
                tanchu:function(){
                    console.log(this.msg);
                }
            }
        });
        //初始化根实例
        new Vue({
            el:"#app"
        });
    </script>
</body>
</html>

注册全局组件

四、注册局部组件

    全局注册往往是不够理想的。全局注册所有的组件意味着即便已经不再使用一个组件了,它仍然会被包含在
 最终的构建结果中。这造成了用户下载的JavaScript的无谓的增加。所以可以在实例选项中注册局部组件,这
 样组件只能在这个实例中使用。

*注册局部组件步骤:
1)通过一个普通的JavaScript对象来定义组件:
        var ComponentA = { }
2)然后在根实例中的components选项中定义想要使用的组件:
new Vue({
        el: ‘#app’,
        components: {
                ‘component-a’: ComponentA
        }
})
*对于components对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
*注意局部注册的组件在其子组件中不可用。例如,希望 ComponentA 在ComponentB中可用,则需要这样写:
var ComponentA = {};
var ComponentB = {
        components: {
                ‘component-a’: ComponentA
        },
}
*或者如果通过Babel和webpack使用ES2015模块,那么代码看起来更像:
import ComponentA from ‘./ComponentA.vue’
export default {
        components: {
                ComponentA
        },
}
*注意在ES2015+中,在对象中放一个类似ComponentA的变量名其实是ComponentA: ComponentA的缩写,即这个变量名同时是用在模板中的自定义元素的名称,包含了这个组件选项的变量名。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>注册局部组件</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <my-component></my-component>
    </div>
    <div class="app">
        <my-component></my-component>
    </div>
    <script>
        //注册局部组件
        var com = {
            template:'<div>{{msg}}<input type="button" value="弹" @click="tanchu"/></div>',
            data:function(){
                return {
                    msg:"Hello"
                };
            },
            methods:{
                tanchu:function(){
                    console.log(this.msg);
                }
            }
        };
        //初始化根实例
        new Vue({
            el:"#app",
            components:{
               'my-component':com
            }
        });
        new Vue({
            el:".app"
            //第二个根实例没有注册my-component这个局部组件,会报错
        });
    </script>
</body>
</html>

五、关于组件名的注意事项

      在注册一个组件时,始终需要给它一个名字。组件名就是 Vue.component 的第一个参数。当直接在DOM中使用一个组件 (而不是在字符串模板或单文件组件) 的时候,强烈推荐遵循W3C规范中的自定义组件名 (字母全小写且必须包含一个连字符)。这会避免当前以及未来的HTML元素相冲突。请注意,Vue.js不对自定义标记名称(全小写,必须包含连字符)强制执行W3C规则,但按照此惯例被认为是良好的做法。

定义组件名的方式有两种:
1)使用kebab-case:Vue.component('my-component-name', {})
   当使用kebab-case(短横线分隔命名)定义一个组件时,也必须在引用这个自定义元素时使用kebab-case,
   例如<my-component-name>。
2)使用PascalCase:Vue.component('MyComponentName', {})
   当使用PascalCase(驼峰式命名)定义一个组件时,在引用这个自定义元素时两种命名法都可以使用。
   尽管如此,直接在DOM(即非字符串的模板)中使用时只有kebab-case是有效的。

六、模板解析

      有些 HTML 元素,诸如 ul、ol、table,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 li、tr,只能出现在其它某些特定的元素内部。这会导致使用这些有约束条件的元素时遇到一些问题。这时候自定义组件会被作为无效的内容提升到外部,并导致最终渲染结果出错。
is 特性给了一个变通的办法:
<table>
<tr is=”blog-post-row”></tr>
</table>
需要注意的是如果从以下来源使用模板的话,这条限制是不存在的:
1)字符串 (例如:template: ‘…’)
2)单文件组件 (.vue)
3)<script type=”text/x-template”>

这些限制中最常见的是:

  • a不能包含其他交互元素(例如按钮和其他链接)
  • li应该是直接孩子ul或ol,两者ul并ol只能包含li
  • option应该是一个直接的孩子select,并且select只能包含option(和optgroup)
  • table只能包含thead,tbody,tfoot和tr,这些元素应该是直接孩子table
  • tr只能包含th和td,而这些元素应该是直接子女的tr

七、组件通讯

1、Prop

    prop是父组件用来传递数据的一个自定义属性。父组件的数据需要通过props把数据传给子组件,
子组件需要显式地用props选项声明"prop":Prop是可以在组件上注册的一些自定义特性。当一个值
传递给一个prop特性的时候,它就变成了那个组件实例的一个属性。

2、静态的Prop

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>静态Prop</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <tip msg="HelloHtml"></tip>
        <tip msg="HelloCss"></tip>
        <tip msg="HelloJavascript"></tip>
    </div>

    <script type="text/x-Template" id="tipTpl">
        <div>
            <input type="button" value="消息弹窗" @click="alterMsg"/>
        </div>
    </script>

    <script>
        var tipTpl = {
            template:'#tipTpl',
            //声明prop
            props:['msg'],
            methods:{
                alterMsg:function(){
                    console.log(this.msg);
                }
            }
        };
        new Vue({
            el:"#app",
            components:{
               'tip':tipTpl
            }
        });
    </script>
</body>
</html>

静态prop

3、动态的Prop

可以用v-bind动态绑定props的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件。
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>动态Prop</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <tip v-bind:msg="a"></tip>
        <tip msg="HelloCss"></tip>
        <tip msg="HelloJavascript"></tip>
    </div>

    <script type="text/x-Template" id="tipTpl">
        <div>
            <input type="button" value="消息弹窗" @click="alterMsg"/>
        </div>
    </script>

    <script>
        var tipTpl = {
            template:'#tipTpl',
            //声明prop
            props:['msg'],
            methods:{
                alterMsg:function(){
                    console.log(this.msg);
                }
            }
        };
        new Vue({
            el:"#app",
            components:{
               'tip':tipTpl
            },
            data:{
                a:'HelloVue'
            }
        });
    </script>
</body>
</html>

动态prop

一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,你会发现我们能够在组件实例中访问这个值,就像访问 data 中的值一样。

一个 prop 被注册之后,你就可以像这样把数据作为一个自定义特性传递进来:




然而在一个典型的应用中,你可能在 data 里有一个博文的数组:

new Vue({
el: ‘#blog-post-demo’,
data: {
posts: [
{ id: 1, title: ‘My journey with Vue’ },
{ id: 2, title: ‘Blogging with Vue’ },
{ id: 3, title: ‘Why Vue is so fun’ },
]
}
})
并想要为每篇博文渲染一个组件:

猜你喜欢

转载自blog.csdn.net/sinat_38328891/article/details/80229230