Vue组件化

1、什么是组件化,将页面拆分成功能块,对功能块进行管理维护,方便复用、管理。一个个功能块就可以看做组件,组件使用可以看做成树模型,一个根组件new Vue,从根到各种各样的组件枝

2、Vue组件化使用步骤

//1、创建组件构造器。在template中ES6使用Tab上面的``编写dom可以直接换行,方便阅读
const cpnConstructor=Vue.extend({
    template:`<div></div>`,
    components:{
        //这是cpnConstructor的子组件
    },
    data(){
        //这是此组件的数据存放区
    }
})
//2、注册此组件
Vue.component('cpn',cpnConstructor)
//3、使用组件
必须在new Vue实例中使用
<div>
    <cpn></cpn>
</div>

const app=new Vue({
    el:'#app',
    data:{}
})

实例:

<body>
<div id="app">
<cpn></cpn> 
</div>
<script src="../js/vue.js"></script>
<script>
    const cpnConstructor =Vue.extend({
        template:`<div><h2>这是页面</h2></div>` ,
        data(){
            return {
                message:"这是message"
            }
        }
    })
    Vue.component('cpn',cpnConstructor)
    const app=new Vue({
        el:"#app",
        data:{

        }
    })

</script>
</body>

3、全局组件,局部组件

全局组件,在Vue实例下都可使用,局部组件只能在注册此组件的实例或者组件中使用

//只能在vue中使用
 const cpnConstructor =Vue.extend({
        template:`<div><h2>这是页面</h2></div>` ,
        data(){
            return {
                message:"这是message"
            }
        }
    }) 
    const app=new Vue({
        el:"#app",
        data:{

        },
        components:{
            cpn:cpnConstructor //或者直接写成cpnConstructor,那么节点就是用<cpnConstructor>
        }
    })
    
//如果在其他实例中的components注册,那么只能在注册此组件的实例或者组件中使用

4、父组件,子组件

//其实就是在一个组件中使用option:components注册其他组件
cosnt cpn1=Vue.extend({
    template:'<div></div>'
})
const cpnConstructor =Vue.extend({
    template:`<div><h2>这是页面</h2></div>` ,
    data(){
        return {
            message:"这是message"
        }
    },
    components:{
        cpn1:cpn1 //或者直接写成cpn1
    }
})
//cpn1是cpnConstructor的子组件

5、注册组件语法糖,

//直接在组件中创建组件
 const app=new Vue({
        el:'#app',
        data:{},
        components:{
            cpn1:{
                template:'<div><h2>这个是cpn1</h2></div>',
                data(){
                    return{
                        message:"这是组件cpn1中的message"
                    }
                }
            },
            cpn2:{
                template:'<div><h2>这是cpn2</h2></div>',
                data(){
                    return{
                        message:"这是组件cpn2中的message"
                    }
                }
            }
        }
    })

6、组件中template分离

//1、直接卸载script中
<script type="text/x-template" id="cpn1">
    <div><h2>这个是cpn1</h2></div>
</script>
//2、写成<template>标签,注意:如果Dom节点比较多,必须先在所有Dom之前加上<div>,如下
<body>
    <template id="cpn2">
        <div>
            <h2>这个是cpn2</h2>
            <p>节点较多,先包含一个div</p>
        </div> 
    </template>

</body>
//使用
const cpn=Vue.extend({
    template:'#cpn1'
})

7、组件数据传输,组件不能直接访问实例数据,组件内部有自己的数据

const cpn=Vue.extend({
    data(){
        return{
            message:"这是cpn的数据"
        }
    }
})
//组件中的数据option,一定要写成function ,并且function返回的是个对象,对象里面是数据
//原因是:因为组件可能会被不同的组件或实例调用,那么此组件必须数据独立,不能多组件公用此组件的数据,如果用function
//作为数据,每次调用组件就会重新创建function

8、父子之间数据通信,比如父组件发起网络请求,那么子组件就不用再次发送请求,可以直接用父组件传来的数据

//父组件传值给子组件使用property
<body>
<div id="app">
    <cpn1 :cmessage="fmessage" :cwords="fwords">
    </cpn1>
</div>
<template id="cpn1">
    <div>
        <h2>{{cmessage}}</h2>
        <h2 v-for="item in cwords">{{item}} </h2>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const app=new Vue({
        el:'#app',
        data:{
            fmessage:"这是父组件的message",
           fwords:\['a','b','c'\]
        },
        components:{
            cpn1:{
                template:'#cpn1',
                data(){
                    return{
                        message:"这是组件cpn1中的message"
                    }
                },
                props:\['cmessage','cwords'\]
            }
        }
    })
</script> 
</body>

//props除了数组,还可以是对象,并且对对象定义数据类型
props:{ 
    //类型:String Number Boolean Array Object Date Function Symbol
    cmovies:Array,
    cmessage:String 
}
//还可以定义默认值,当<cpn>不绑定属性的时候,显示默认值
props:{
    cmessage:{
     type:String,
     default:'aaaaa', 
    },
    cage:{
        type:Number,
        required:true
    },
    //类型是对象或者数组时,默认值必须是一个函数,初始化
    cmovies:{
        type:Array,
        default(){
            return \['a','b','c'\]
        }
    },
    cinfo:{
        type:Object,
        default(){
            return {}
        }
    }
}
//props中的驼峰标识
//目前<cpn>绑定的时候 不支持驼峰命名
<cpn :cinfo="fInfo">  //这是正确的
<cpn :cInfo="fInfo"> //这是错误的
如果props中的属性名是由驼峰构成,正确写法
<cpn :c-info="fInfo">

9、子组件传数据父组件通过$emit,比如子组件切换tab事件需要告诉父组件切换的id,让父组件知道id请求服务器获取数据发给子组件

 //流程,点击Tab按钮切换子组件tab,触发子组件点击事件,点击事件通过$emit自定义事件给父组件中的<cpn> 标签做v-on事件监听
 
<body>
<div id="app">
    <!-- getclik去掉参数,默认获得子组件发射过来的$emit(itemclick,item)中的item值-->
    <cpn @itemclick="getClick"></cpn>
</div>
<template id="cpn">
    <div>
        <!--监听子组件的按钮点击事件,并把item作为参数传入-->
    <button v-for="item in catagories" @click="btnClick(item)">{{item.name}}</button>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const cpn=Vue.extend({
        template:"#cpn",
        data(){
            return{
                catagories:\[
                    {id:1,name:"热门文章"},
                    {id:2,name:"冷门文章"},
                    {id:3,name:"不冷不热"}
                \]

            }
        },
        methods:{
            btnClick(item){
                //自定义事件,给父组件v-on绑定使用
                this.$emit("itemclick",item);
            }
        }
    })
    const app = new Vue({
        el: "#app",
        data: {},
        components:{
            //注册子组件
            cpn
        },
        methods:{
            //父组件中调用事件
            getClick(item){
                console.log(item.id);
                //获取id请求数据,更改父组件中数据
            }
        }
    });
</script> 
</body>

[如有错误请留言指正]