组件的声明 #

https://www.w3.org/TR/html/syntax.html#void-elements

组件的数据 #

在组件中的数据必须是函数的形式

'MyButton':{
    data(){
        return {content:'按钮'}
    },
    template:'<button>{{content}}</button>'
}

组件的属性应用及校验 #

属性应用 #

<my-button button-content="按钮"></my-button>
components:{
    'MyButton':{
        props:['buttonContent'],
        template:'<button>{{buttonContent}}</button>'
    }
}

属性在组件标签上需要使用短横线命名法,在组件中声明需要采用驼峰命名法

属性校验 #

<my-button button-content="按钮" :number="'1'"></my-button>
components:{
    'MyButton':{
        props:{
            buttonContent:String,
            arr:{
                type:Array,
                default:()=>([])
            },
            number:{
                type:Number,
                validator:(value)=>{
                    return typeof value == 'number'
                }
            },

        },
        template:'<button>{{buttonContent}} {{arr}} {{number}}</button>'
    }
}

批量传入数据 #

<my-button v-bind="info"></my-button>
let vm = new Vue({
    el:'#app',
    data:{
        info:{name:'姜文',age:18}
    },
    components:{
        'MyButton':{
            props:['name','age'],
            inheritAttrs:false,
            mounted(){
                console.log(this.$attrs)
            },
            template:'<button>{{name}} {{age}} </button>'
        }
    }
});

事件应用 #

<!-- 给组件绑定方法,在内部触发绑定的方法 -->
<my-button @click="change" msg="按钮"></my-button>
let vm = new Vue({
    el:'#app',
    methods:{
        change(){ alert('hello'); }
    },
    components:{
        'MyButton':{
            props:['msg'],
            template:`<div>
                <button @click="this.$listeners.click">{{msg}}</button>
                <button v-on="this.$listeners">{{msg}}</button>
                <button @click="$emit('click')"></button>
            </div>`
        }
    }
});

在组件的根元素上直接监听一个原生事件

<my-button @click.native="change"></my-button>

\$parent & \$child #

实现收缩面板功能

<collapse>
    <collapse-item title="react">内容1</collapse-item>
    <collapse-item title="vue">内容2</collapse-item>
    <collapse-item title="node">内容3</collapse-item>
</collapse>  
Vue.component('Collapse',{
    methods:{
        open(id){
            this.$children.forEach(child => {
                if(child._uid != id){
                    child.show = false;
                }
            });
        }
    },
    template:`<div class="wrap">
        <slot></slot>
    </div>`
});
Vue.component('CollapseItem',{
    props:['title'],
    data(){
        return {show:true}
    },
    methods:{
        change(){
            this.$parent.open(this._uid);
            this.show =!this.show;
        }
    },  
    template:`<div class="collapse-item" @click="change">
        <div class="title">{{title}}</div>
        <div v-show="show">
            <slot></slot>    
        </div>
    </div>`
});

v-slot应用 #

Provide & inject #

跨组件数据传递,主要为高阶插件/组件库提供用例

provide:{ name:'zf' },
components:{
    list:{
        inject:['name'],
        template:`<div>{{name}}</div>`
    }
}

父子组件数据同步 #

.sync 和 v-model的使用

<div id="app">
        {{msg}}
        <tab :msg="msg" @update:msg="change"></tab>
        <tab :msg.sync="msg"></tab>
        <tab v-model="msg"></tab>
</div>


let vm = new Vue({
    el:'#app',
    data:{
        msg:'hello'
    },
    methods:{
        change(value){
            this.msg = value
        }
    },
    components:{
        tab:{
            props:['msg'],
            methods:{
                change(){
                    this.$emit('update:msg','world')
                    this.$emit('input','world');
                }
            },
            template:`<div>
                {{msg}} <button @click="change">切换</button>
            </div>`
        }
    }
})

ref 特性 #

// 在组件中可以获取组件实例
<tab :msg="msg" @update:msg="change" ref="ele"></tab>
this.$refs.ele.change()

// 放在dom上表示获取当前dom元素
<div ref="ele"></div>
this.$refs.ele.style.border="1px solid red"

// 在v-for中获取的是集合
<template v-for="a in 3">
    <tab :msg="msg" @update:msg="change" ref="ele" :key="a"></tab>
</template>
console.log(this.$refs.ele.length)

组件间通信 #

异步组件 #

Vue.component('async', function (resolve, reject) {
    setTimeout(function () {
        resolve({
            template: '<div>异步组件</div>'
        })
    }, 1000);
});

在后期我们一般配合webpack的import语法使用

递归组件 #