Vue的组件component(一)

来源:互联网 发布:linux 文件权限所有者 编辑:程序博客网 时间:2024/05/01 16:16

Vue本身是基于组件化开发的,每个组件相当于一个Vue实例。Vue的组件部分搞清楚,是学好Vue的重要一步。

相关demo示例的github地址:vue-component

https://github.com/liwudi/Vue.git

1、Vue组件的全局注册

要注册一个全局组件,可以使用 Vue.component(tagName, options)。例如:

Vue.component('my-component', {  // 选项})

使用的时候直接在dom中使用组件名。例如:

<my-component></my-component>

下面是一个完整的带有属性传递的组件应用实例:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Vue-demo</title>    <script src="https://cdn.jsdelivr.net/npm/vue"></script></head><body><div id="app">    <ol>        <!--使用组件-->        <todo-item                v-for="item in todoList"                v-bind:todo="item"        ></todo-item>    </ol></div><script>    //定义一个最简单的组件    Vue.component('todo-item',{        props:['todo'],        template:'<li>name:{{todo.name}},age:{{todo.age}}</li>'    });    new Vue({        el:'#app',        data:{            todoList:[{name:'张三',age:23},{name:'李四',age:24},{name:'王五',age:25}]        }    });</script></body></html>

2、Vue组件的局部注册

可以通过Vue实例/组件示例的实例选项 components 来注册属于他们自己的组件。

var Child = {    template:"<p>我是中国人</p>"}new Vue({    el:'#app',    components: {         "my-comp": Child    }})

一个完整的局部组件注册的示例demo:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Vue-demo</title>    <script src="https://cdn.jsdelivr.net/npm/vue"></script></head><body><div id="app">    <todo-item></todo-item></div><script>    var Child = {        template: '<div>A custom component!</div>'    };    new Vue({        el:'#app',        components:{            'todo-item': Child        }    });</script></body></html>

3、组件中的data应该是函数

在new Vue()的实例的过程中,data可以是一个对象,但是在组件component中,data是一个函数。

下面的写法在Vue中会报错。

Vue.component('my-com',{        template:'<span>{{message}}</span>',        data: {            message: 1        }    })

这个示例才是正确的写法:

Vue.component('my-com',{   template:'<span>{{message}}</span>',    data: function () {        return {            message: 1        }    }})

4、组件应该是组合使用的

在react中,最外层是一个根组件,里层的组件被一层层的嵌套在外层组件内,从而形成一个组件树。

在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。

使用props传递数据的语法:

Vue.component('child', {  // 声明 props  props: ['message'],  // 就像 data 一样,prop 也可以在模板中使用  // 同样也可以在 vm 实例中通过 this.message 来使用  template: '<span>{{ message }}</span>'})

4_1、通过props进行属性传递的demo

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Vue-demo</title>    <script src="https://cdn.jsdelivr.net/npm/vue"></script></head><body><div id="app">    <ol>        <!--使用组件-->        <my-com                v-bind:todo="message"        ></my-com>    </ol></div><script>    //定义一个最简单的组件    Vue.component('my-com',{        props:['todo'],        template:'<h3>{{todo}}</h3>'    });    new Vue({        el:'#app',        data:{            message:'hello!'        }    });</script></body></html>

5、camelCase vs. kebab-case

两者的区别是驼峰式命名规则,以及短横线分隔式命名。

在JavaScript中,如果使用驼峰式命名camelCase。

由于在HTML中不区分大小写,我们需要转换成短横线分隔式命名kebab-case。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Vue-demo</title>    <script src="https://cdn.jsdelivr.net/npm/vue"></script></head><body><div id="app">    <ol>        <!--使用组件-->        <todo-item                my-todo="hello"        ></todo-item>    </ol></div><script>    //定义一个最简单的组件    Vue.component('todo-item',{        props:['myTodo'],        template:'<h2>{{myTodo}}</h2>'    });    new Vue({        el:'#app'    });</script></body></html>

6、动态props

一般使用V-bind的方式,把一个属性动态的绑定到props。

<todo-com v-bind:todo='message'></todo-com>

如果没有v-bind,就会展示message这个字符串;但是现在,展示的是在data中动态绑定的变量message的信息。

下面是一个动态绑定props的示例:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Vue-demo</title>    <script src="https://cdn.jsdelivr.net/npm/vue"></script></head><body><div id="app">    <ol>        <!--使用组件-->        <todo-item                v-bind:my-todo="message"        ></todo-item>    </ol></div><script>    //定义一个最简单的组件    Vue.component('todo-item',{        props:['myTodo'],        template:'<h2>{{myTodo}}</h2>'    });    new Vue({        el:'#app',        data: {            message: 'hello world!'        }    });</script></body></html>

7、动态props,绑定一个对象作为props传递给子组件。

比如一个对象是这样的:

todo: {  text: 'Learn Vue',  isComplete: false}

然后:

<todo-item v-bind="todo"></todo-item>

等价于:

<todo-item  v-bind:text="todo.text"  v-bind:is-complete="todo.isComplete"></todo-item>

一个完整的示例demo如下:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Vue-demo</title>    <script src="https://cdn.jsdelivr.net/npm/vue"></script></head><body><div id="app">    <todo-com v-bind="todo"></todo-com></div><script>    //定义一个最简单的组件    Vue.component('todo-com',{        props:['text','isComplete'],        template:'<h2>I has {{isComplete ? "completed ":"not completed "}}{{text}}</h2>'    });    new Vue({        el:'#app',        data: {            todo:{                text: 'Learn Vue',                isComplete: false            }        }    });</script></body></html>

8、组件通信,props传递子组件的使用场景。

1、在子组件中获取props的值,并且在子组件中需要改变这个值。

我们可以定义一个局部变量把props的值赋值给它。

props: ['initialCounter'],data: function () {  return { counter: this.initialCounter }}

2、在子组件中需要把这个props进行一定的处理,再进行使用。

定义一个计算属性,处理 prop 的值并返回

props: ['size'],computed: {  normalizedSize: function () {    return this.size.trim().toLowerCase()  }}

9、props验证

要指定验证规则,需要用对象的形式来定义 prop,而不能用字符串数组:

Vue.component('example', {  props: {    // 基础类型检测 (`null` 指允许任何类型)    propA: Number,    // 可能是多种类型    propB: [String, Number],    // 必传且是字符串    propC: {      type: String,      required: true    },    // 数值且有默认值    propD: {      type: Number,      default: 100    },    // 数组/对象的默认值应当由一个工厂函数返回    propE: {      type: Object,      default: function () {        return { message: 'hello' }      }    },    // 自定义验证函数    propF: {      validator: function (value) {        return value > 10      }    }  }})

10、非props特性

所谓的非props特性是不用props申明,直接传给子组件的一些特性。比如: class。

一般而言,父组件的非props特性对子组件的特性进行覆盖和合并。

下面的示例中,如果父组件不使用class=’color2’,则数组颜色是红色,如果使用了,则颜色为绿色。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Vue-demo</title>    <style>        .color1{            color: red;        }        .color2{            color: green;        }    </style>    <script src="https://cdn.jsdelivr.net/npm/vue"></script></head><body><div id="app">    <foo-component class="color2" v-bind:foo-message="fooMessage"></foo-component></div><script>    var fooComponent = {        props: ['fooMessage'],        template: '<div class="color1"> {{ fooMessage }} </div>'    };     var vm = new Vue({         components: {            'foo-component': fooComponent         },         el: '#app',         data: {             fooMessage: 12345         }     });</script></body></html>

11、自定义事件(子组件向父组件传值。)

使用 $emit(eventName) 触发一个事件。

使用 $on(eventName) 接受一个事件。

但是一般使用的时候,使用 v-on:eventName = eventFunction 的方式定义事件。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Vue-demo</title>    <script src="https://cdn.jsdelivr.net/npm/vue"></script></head><body><div id="app">    <button-com v-on:parent="myEvent"></button-com></div><script>    var Child = {        template:'<button v-on:click="childEvent"> {{ num }} </button>',        data: function () {            return {                num: 0            }        },        methods:{            childEvent: function () {                this.num += 1;                this.$emit("parent",this.num);            }        }    };    var vm = new Vue({        el:'#app',        data:{            total: 0        },        components: {            'button-com': Child        },        methods: {            myEvent: function (data) {                console.log(data);            }        }    })</script></body></html>

12、.sync修饰符

<comp :foo.sync="bar"></comp>

等价于

<comp :foo="bar" @update:foo="val => bar = val"></comp>

当子组件需要更新 foo 的值时,它需要显式地触发一个更新事件:

this.$emit('update:foo', newValue)

下面是完整的demo

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Vue-demo</title>    <script src="https://cdn.jsdelivr.net/npm/vue"></script></head><body><div id="app">    <div>{{bar}}</div>    <my-comp :foo.sync="bar"></my-comp></div><script>    Vue.component('my-comp', {        template: '<div @click="increment">{{copyFoo}}点我+1</div>',        data: function() {            return {copyFoo: this.foo}        },        props: ['foo'],        methods: {            increment: function() {                this.$emit('update:foo', ++this.copyFoo);            }        }    });    new Vue({        el: '#app',        data: {bar: 0}    });</script></body></html>
原创粉丝点击