Vue笔记(二):Components

组件注册


<!-- 组件使用 -->
<div id="exp">
    <my-component></my-component>
</div>
// 1. 全局注册 任何地方都可使用
Vue.component('my-component', {
    props: ['msg'],
    template: '<span>this is my component!</span>',
    data: function(){
        return {
            ...
        }
    }
});

// 2. 创建根实例
new Vue({
    el: '#exp',
    data: {}
});
注意:
    组件中的 data 必须是一个函数,否则 Vue 会停止工作。这样做是为了避免多个组件实例引用同一个 data 对象,导致彼此相互影响。换句话说,是为了保证组件实例间的相互独立,而这是通过每次调用 data 函数返回一个新对象来实现的。

Props


1. 字面量语法

组件实例的作用域是孤立的,不能在子组件的模板内直接引用父组件的数据。如果子组件要引用父组件的数据,需要使用 props 属性。

Vue.component('child', {
  props: ['myName'], // 声明 props
  template: '<span>{{ myName }}</span>'
});

这里的 props 就如同实例中的 data 对象,也可以在实例中以 this.myName 形式使用。

<child my-name="hello!"></child>
注意:
    HTML 特性不区分大小写。使用驼峰式命名的 prop 需要转换为相对应的短横线隔开式命名。
    myName --> my-name

2. 动态语法:v-bind

类似于用 v-bind 绑定 HTML 特性,我们也可用 v-bind 将动态 props 绑定到父组件中的数据。实现父组件与子组件数据变化的传递。

<div id="exp-1">
    <input v-model="parentMsg">
    <child :msg="parentMsg"></child>
</div>
new Vue({
    el: '#exp-1',
    data: {
        parentMsg: 'parent message'
    },
    components: {
        child: {
            props: ['msg'],
            template: '<button>{{msg}}</button>'
        }
    }
});
注意:
    这种数据绑定是单向的,父组件数据会影响子组件数据,但子组件数据不会影响父组件。

3. Prop验证

我们可以为组件的 props 指定验证规格。如果传入的数据不符合规格,Vue 会发出警告。

Vue.component('my-component', {
    props: {
        prop1: 'null', // 任何类型皆可
        prop2: [String, Number], // 指定多种类型
        prop3: {
            type: Number,
            reuqired: true, // 属性必需且为数值型
            default: 20, // 指定默认值
            twoway: true, // 指定此prop为双向绑定 2.0移除
            validator: function(v){ // 自定义验证器
                return v > 10
            }
        }
    }
});

props 验证失败时, Vuejs 将拒绝在子组件上设置此值。

组件通信 / 2.0+


1. v-on 绑定自定义事件

$on 监听事件:vm.$on('eventName', handler)

$emit 触发事件:vm.$emit('eventName', args)

<div id="exp-2">
    <h4>Total:{{total}}</h4>
    <my-btn @customEvt="reduceNum">{{counter}}</my-btn>
    <my-btn @customEvt="reduceNum">{{counter}}</my-btn>
</div>

在使用子组件的地方直接用 v-on:customEvt 来监听子组件事件的触发,来实现父子组件的通信。

Vue.component('my-btn', {
    template: '<button @click="addNum">{{counter}}</button>',
    data: function(){
        return {
            counter: 0
        }
    },
    methods: {
        addNum: function(){
            this.counter++;
            this.$emit('customEvt');
        }
    }
});

new Vue({
    el: '#exp-2',
    data: {
        total: 0
    },
    methods: {
        reduceNum: function(){
            this.total++;
        }
    }
});

2. 双向绑定的两种简单实现

# v-model + watch

  1. 由于子组件内部 props 不可写,因此我们需要在 data 对象中创建一个副本并将其初始为 props 属性的值。
  2. 组件外修改 props 并不会同步到副本中,因此我们设置一个侦听器 watchprops 与其副本数据同步。
  3. 监听副本状态变化,触发事件回调 this.$emit('input', val)
  4. 最后结合 v-model 将子组件的数据传递到外部,父组件数据响应式改变。
<template id="temp">
    <div>
        <input v-model="myname">
        <button>{{myname}}</button>
    </div>
</template>
<div id="exp-3">
    <h3>父组件</h3>
    <input v-model="name">
    <button>{{name}}</button>
    
    <h3>子组件</h3>
    <child :sname="name" v-model="name"></child>
</div>

new Vue({
    el: '#exp',
    data: {
        name: 'zz'
    },
    components: {
        'child': {
            template: '#temp',
            props: ['sname'],
            data: function(){
                return {
                    myname: this.sname  // 1
                }
            },
            watch: {
                sname: function(val){
                    this.myname = val;  // 2
                },
                myname: function(val){
                    this.$emit('input', val);  // 3
                }
            }
        }
    }
});

JS Bin - watch 双向绑定

# props + obj

将一个引用类型传递给 props 属性,由于对象的地址引用特性,子组件修改对象属性父组件数据也相应改变。借此实现组件数据的双向绑定。

<template id="temp">
    <div>
        <input v-model="obj.name">
        <button>{{obj.name}}</button>
    </div>
</template>

<div id="exp">
    <h3>父组件</h3>
    <input v-model="obj.name">
    <button>{{obj.name}}</button>
        
    <h3>子组件</h3>
    <child :obj="obj"></child>
</div>
new Vue({
    el: '#exp',
    data: {
        obj:{
            name: 'oo'
        }
    },
    components:{
        'child':{
            template: '#temp',
            props: ['obj']
        }
    }
});

JS Bin - 对象props双向绑定

posted @ 2017-10-17 21:12  tt273z  阅读(377)  评论(0编辑  收藏  举报