vue.js之组件

代码复用一直是软件开发中长期存在的问题,每个开发者都想要再次使用之前写好的代码,又担心引入这段代码后对现有的程序产生影响。现在web Components的出现提供了一种新的思路,可以自定义tag标签,并拥有自身的模板,样式和交互。Vue.js提供了自己的组件系统,支持自定义tag元素和原生HTML元素的扩展

一、基本步骤

  1、vue的组件使用有三个步骤:创建组件构造器、注册组件和使用组件

  • 调用Vue.extend({...})创建组件构造器
  • 用Vue.component()方法注册组件
  • 在Vue实例的作用范围内使用组件

下面的代码演示了这三个步骤

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue组件</title>
  <script src="bower_components/vue/dist/vue.js"></script>
</head>
<body>
<div id="box">
    <!--#box是vue实例挂载的元素,应该在挂载元素范围内使用组件-->
    <aaa></aaa>
</div>
<script>
    <!--定义一个组件-->
    // 全局组件
    //1.创建一个组件构造器
    var Aaa=Vue.extend({
        template:'<h3> 我是标题3</h3>'
    });
    //2.注册组件,并指定组件的标签,组件的HTML标签为<aaa>
    Vue.component('aaa',Aaa);
    var vm=new Vue({
        el:"#box"
    })
</script>
</body>
</html>

 运行结果:

  2、理解组件的创建和注册
  • Vue.extend()是Vue构造器的扩展,调用Vue.extend()创建的是一个组件构造器。

  •  Vue.extend()构造器有一个选项对象,选项对象的template属性用于定义组件要渲染的HTML。 

  • 使用Vue.component()注册组件时,需要提供2个参数,第1个参数时组件的标签,第2个参数是组件构造器。 
  •  组件应该挂载到某个Vue实例下,否则它不会生效。

 

<!DOCTYPE html>
<html>
    <body>
        <div id="app1">
            <my-component></my-component>
        </div>
        
        <div id="app2">
            <my-component></my-component>
        </div>
        
        <!--该组件不会被渲染-->
        <my-component></my-component>
    </body>
    <script src="js/vue.js"></script>
    <script>
        var myComponent = Vue.extend({
            template: '<div>This is a component!</div>'
        });
        
        Vue.component('my-component', myComponent);
        
        var app1 = new Vue({
            el: '#app1'
        });
        
        var app2 = new Vue({
            el: '#app2'
        })
    </script>
</html>

 

注意:虽然上面有三个地方使用了<my-component>标签,但是只有#app1和#app2下的<my-component>标签才起到作用。因为第三个没有被挂载

二、全局注册与局部注册

1、全局注册

  全局注册需要确保在根实例初始化之前注册,这样才能使组件在任意实例中被使用,注册方式如下:

 

<!DOCTYPE html>
<html>
    <body>
        <div id="app1">
            <my-component></my-component>
        </div>
  </body>
    <script src="js/vue.js"></script>
    <script>
        var myComponent = Vue.extend({
            template: '<div>This is a component!</div>'
        })
        
        Vue.component('my-component', myComponent)        //这条语句应该写在var app1=new Vue({....})之前,注册成功之后,就可以在模块中以自定义元素<my-cpmponent>的形式使用组件
        
        var app1 = new Vue({
            el: '#app1'
        });</script>
</html>

 

运行结果:  

This is a component!

2、局部注册

  组件内使用其他组件,可以用选项对象的components属性实现局部注册。

  

<!DOCTYPE html>
<html>
    <body>
        <div id="app">
            <!-- 3. my-component只能在#app下使用-->
            <my-component></my-component>
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>
        // 1.创建一个组件构造器
        var myComponent = Vue.extend({
            template: '<div>This is my first component!</div>'
        })
        
        new Vue({
            el: '#app',
            components: {
                // 2. 将myComponent组件注册到Vue实例下
                'my-component' : myComponent
            }
        });
    </script>
</html>

 三、父组件与子组件

  在 组件中定义并使用其他组件,这就构成了父子组件的关系 

<!DOCTYPE html>
<html>
    <body>
        <div id="app">
            <parent-component>
            </parent-component>
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>
        
        var Child = Vue.extend({
            template: '<p>This is a child component!</p>'
        })
        
        var Parent = Vue.extend({
            // 在Parent组件内使用<child-component>标签
            template :'<p>This is a Parent component</p><child-component></child-component>',
            components: {
                // 局部注册Child组件,该组件只能在Parent组件内使用
                'child-component': Child
            }
        })
        
        // 全局注册Parent组件
        Vue.component('parent-component', Parent)
        
        new Vue({
            el: '#app'
        })
        
    </script>
</html>

 

 运行结果:

理解上面的代码:

  1. var Child = Vue.extend(...)定义一了个Child组件构造器
  2. var Parent = Vue.extend(...)定义一个Parent组件构造器
  3. components: { 'child-component': Child },将Child组件注册到Parent组件,并将Child组件的标签设置为child-component
  4. template :'<p>This is a Parent component</p><child-component></child-component>',在Parent组件内以标签的形式使用Child组件。
  5. Vue.component('parent-component', Parent) 全局注册Parent组件
  6. 在页面中使用<parent-component>标签渲染Parent组件的内容,同时Child组件的内容也被渲染出来

 四、组件注册语法糖

  前面组件注册的方式有点繁琐,Vue.js为了简化这个过程,提供了注册语法糖

  1、使用vue.componet()直接创建和注册组件

// 全局注册,my-component1是标签名称
Vue.component('my-component1',{
    template: '<div>This is the first component!</div>'
})

var vm1 = new Vue({
    el: '#app1'
})

 

  Vue.component()的第1个参数是标签名称,第2个参数是一个选项对象,使用选项对象的template属性定义组件模板。
       使用这种方式,Vue在背后会自动地调用Vue.extend()

  2、在选项对象的components属性中实现局部注册:

var vm2 = new Vue({
    el: '#app2',
    components: {
        // 局部注册,my-component2是标签名称
        'my-component2': {
            template: '<div>This is the second component!</div>'
        },
        // 局部注册,my-component3是标签名称
        'my-component3': {
            template: '<div>This is the third component!</div>'
        }
    }
})

 

 

五、使用template和javascript标签

  尽管语法糖简化了组件注册,但在template选项中拼接HTML元素比较麻烦,这也导致了HTML和JavaScript的高耦合性。
  庆幸的是,Vue.js提供了两种方式将定义在JavaScript中的HTML模板分离出来。

  1、使用javascript

    

<!DOCTYPE html>
<html>
    <body>
        <div id="app">
            <my-component></my-component>
        </div>
        <!--type指定为text/x-template,意在告诉浏览器这不是一段js脚本,浏览器在解析HTML文档时会忽略<script>标签内定义的内容-->
        <script type="text/x-template" id="myComponent">
            <div>This is a component!</div>
        </script>
    </body>
    <script src="js/vue.js"></script>
    <script>
        
        Vue.component('my-component',{
            template: '#myComponent'          //与上面的模版id相对应

}) new Vue({ el: '#app' }) </script> </html>

 

 template选项现在不再是HTML元素,而是一个id,Vue.js根据这个id查找对应的元素,然后将这个元素内的HTML作为模板进行编译

 运行结果:

 

 2、使用template标签

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
            <my-component></my-component>
        </div>
        <!--使用template标签不需要使用type属性-->
        <template id="myComponent">
            <div>This is a component!</div>
        </template>
    </body>
    <script src="js/vue.js"></script>
    <script>
        
        Vue.component('my-component',{
            template: '#myComponent'
        })
        
        new Vue({
            el: '#app'
        })
        
    </script>
</html>

 

 在理解了组件的创建和注册过程后,我建议使用<script>或<template>标签来定义组件的HTML模板。
这使得HTML代码和JavaScript代码是分离的,便于阅读和维护。

六、使用个props

  组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把数据传给子组件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="bower_components/vue/dist/vue.js"></script>
    <style>
    </style>
</head>
<body>
<div id="box">
    <div>{{a}}</div>
    <aaa>
        {{msg}}
    </aaa>
</div>

<template id="aa">
    <h1>11111</h1>
<!--将父组件数据通过已定义好的props属性传递给子组件--> <bbb :mmm="msg2" :my-msg="msg"></bbb> </template> <script> var vm=new Vue({ el:'#box', data:{ a:'a' }, components:{ 'aaa':{ data(){ return { msg:111, msg2:'我是父组件的数据' } }, template:'#aa', components:{ 'bbb':{ props:{ 'mmm':String, 'myMsg':Number }, template:'<h3>我是bbb组件->{{mmm}} <br> {{myMsg}}</h3>' } } } } }); </script> </body> </html>

 运行结果:

注意:在子组件中定义prop时,使用了camelCase命名法。由于HTML特性不区分大小写,camelCase的prop用于特性时,需要转为 kebab-case(短横线隔开)。例如,在prop中定义的myName,在用作特性时需要转换为my-name。

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

posted @ 2018-01-10 22:32  傅杰  阅读(219)  评论(0编辑  收藏  举报