组件-注册

1.注册组件的基本步骤

(1)创建组件构造器

调用Vue.extend()方法,创建组件构造器

(2)注册组件

调用Vue.component()方法,注册组件

(3)使用组件

在Vue实例的作用范围内使用组件

      <div id="app">
        //3.使用组件
        <my-cpn></my-cpn>
      </div>
      <script type="text/javascript">
        //ES6 ``可换行
        
        //1.创建组件构造器
        const cpn = Vue.extend({
            template:`
                <div>
                    <h2>我是标题</h2>
                    <p>我是内容1</p>
                    <p>我是内容2</p>
                </div>
            `
        })
        
        //2.注册组件(全局组件)
        Vue.component('my-cpn',cpn)         
      </script>

2.注册组件步骤解析

image.png

image.png

3.全局组件和局部组件

(1)全局组件(见如上代码)

(2)局部组件

只能在id为app的div中使用

       const app = new Vue({
            el:'#app',
            data:{
                message:'你好啊'
            },
            components:{
                // cpn使用组件时的标签名
                cpn: cpn
            }
        })

4.父组件与子组件

     <script type="text/javascript">            
        // 1.创建第一个组件
        const cpnC1 = Vue.extend({
            template:`
                <div>
                    <h2>我是标题1</h2>
                    <h2>我是标题2</h2>
                </div>
            `
        })
        
        // 2.创建第二个组件
        const cpnC2 = Vue.extend({
            template:`
                <div>
                    <h2>我是标题3</h2>
                    <h2>我是标题4</h2>
                    <cpn1></cpn1>
                </div>
            `,
            components:{
                cpn1:cpnC1 //子组件注册
            }
        })          
        
        //root组件
        const app = new Vue({
            el:'#app',
            data:{
                message:'你好啊'
            },
            components:{
                cpn2:cpnC2
            }
        })
    </script>

5.组件的语法糖注册方式

(1)全局组件

        Vue.component('cpn1',{
            template:`
                <div>
                    <h2>我是标题1</h2>
                    <h2>我是标题2</h2>
                </div>
            `
        })

(2)局部组件

    components:{
        cpn2:{
            template:`
                <div>
                    <h2>我是标题3</h2>
                    <h2>我是标题4</h2>
                </div>
            `
        }
    }

6.组件模板的分离写法

(1)script标签写法

    <script type="text/x-template" id="cpn1">
        <div>
            <h2>我是标题1</h2>
            <h2>我是标题2</h2>
        </div>
    </script>

(2)template标签写法

    <template id="cpn2">
        <div>
            <h2>我是标题3</h2>
            <h2>我是标题4</h2>
        </div>
    </template>

7.组件数据的存放

注意:data为一个函数,必须有返回值

        Vue.component('cpn',{
            template:'#cpn',
            //data写在此处,值的改变不会相互影响
            data(){
                return{
                    title:'我是标题1'
                }
            }
        })

这样写时,data会一同改变

       const obj = {
            counter:0
        }
        Vue.component('cpn',{
            template:'#cpn',
            data(){
                return obj
            }

8.父子组件间的通信

父传子:props
子传父:自定义事件emit


image.png

1.通过props向子组件传递数据(父传子)

(1)props基本用法

在组件中,使用选项props来声明需要从父级接收到的数据。

props的值有两种方式:

方式一:字符串数组,数组中的字符串就是传递时的名称;
方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。

(2)最简单的props传递

    <div id="app">
        <!-- 通过:cmovies="movies"将data数据传递给了props -->
        <cpn :cmovies="movies" :cmessage="message"></cpn>
        <!-- 省去v-bind,movies会被解析为一个字符串 -->
        <!-- <cpn cmovies="movies" cmessage="message"></cpn> -->
    </div>
    
    <template id="cpn">
        <div>
            <ul>
                <li v-for="item in cmovies">{{item}}</li>
            </ul>
            <h2>{{cmessage}}</h2>
        </div>
    </template>
    
    <script src="../vue/vue.js" type="text/javascript"></script>
    <script type="text/javascript">
        const cpn = {
            template:'#cpn',
            //传递数组的形式
            props:['cmovies','cmessage']
        }
        
        const app = new Vue({
            el:'#app',
            data:{
                message:'你好啊',
                movies:['海王','海贼王','海尔兄弟']
            },
            components:{cpn}
        })
    </script>

(3)props数据验证

除了数组之外,我们也可以使用对象,当需要对props进行类型等验证时,就需要对象写法了。

验证支持的数据类型:String、Number、Boolean、Array、Object、Data、Function、Symbol
当我们有自定义的构造函数时,验证也支持自定义的类型
image.png

(4)props的驼峰标识

数据为驼峰命名时,在引用组件时,v-bind不支持驼峰标识

    <div id="app">
        <cpn :cInfo="info"></cpn>
    </div>
    
    <template id="cpn">
        <div>
            <h2>{{cInfo}}</h2>
        </div>
    </template>
    
    <script src="../vue/vue.js" type="text/javascript"></script>
    <script type="text/javascript">
        const cpn = {
            template:'#cpn',
            props:{
                cInfo:{
                    type:Object,
                    default(){
                        return {}
                    }
                }
            }
        }
        const app = new Vue({
            el:'#app',
            data:{
                info:{
                    name:'gjj',
                    age:21,
                    height:1.75
                }
            },
            components:{
                cpn
            }
        })
    </script>

结果将为默认值

image.png

引用时应该将数据名改为<cpn :c-info="info"></cpn>

2.通过事件向父组件发送消息(子传父)

自定义事件流程:在子组件中,通过$emit()来触发事件,在父组件中,通过v-on来监听子组件事件

子组件:

        const cpn = {
            template:'#cpn',
            data(){
                return {
                    categories:[
                        {id:'aaa',name:'热门推荐'},
                        {id:'bbb',name:'手机数码'},
                        {id:'ccc',name:'家用家电'},
                        {id:'ddd',name:'电脑办公'},
                    ]
                }
            },
            methods:{
                btnClick(item){
                    //发射事件:自定义事件
                    this.$emit('itemclick',item)
                }
            }
        }

父组件:

          const app = new Vue({
            el:'#app',
            data:{
                info:{
                    name:'gjj',
                    age:21,
                    height:1.75
                }
            },
            components:{cpn},
            methods:{
                cpnClick(item){
                    console.log(item)
                }
            }
        })

组件模板部分

    <!-- 父组件模板 -->
    <div id="app">
        <cpn @itemclick="cpnClick"></cpn>
    </div>
    
    <!-- 子组件模板 -->
    <template id="cpn">
        <div id="">
            <button type="button" v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
        </div>
    </template>

3.父子组件双向通信(案例)

<body>
    
    <div id="app">
        <cpn :cnum1="num1" :cnum2="num2" @num1change="num1Change" @num2change="num2Change"></cpn>
    </div>
    
    <template id="cpn">
        <div id="">
            <h2>props:{{cnum1}}</h2>
            <h2>{{dnum1}}</h2>
            <input type="text" :value="dnum1" @input="num1Input"/>
            <h2>props:{{cnum2}}</h2>
            <h2>{{dnum2}}</h2>
            <input type="text" v-model="dnum2" @input="num2Input"/>
        </div>
    </template>
    
    <script src="../vue/vue.js" type="text/javascript"></script>
    <script type="text/javascript">
        const app = new Vue({
            el:'#app',
            data:{
                num1:1,
                num2:2
            },
            methods:{
                num1Change(num){
                    this.num1 = parseInt(num)
                },
                num2Change(num){
                    this.num2 = parseInt(num)
                }
            },
            components:{
                cpn:{
                    template:'#cpn',
                    props:{
                        cnum1:Number,
                        cnum2:Number
                    },
                    data(){
                        return{
                            dnum1:this.cnum1,
                            dnum2:this.cnum2
                        }
                    },
                    methods:{
                        num1Input(event){   
                            this.dnum1 = event.target.value;
                            console.log(this.dnum1)                                                               
                            this.$emit('num1change',this.dnum1) //不能使用驼峰命名
                        },
                        num2Input(){
                            this.$emit('num2change',this.dnum2)
                        }
                    }
                }
            }
        })
    </script>
    
</body>

watch实现方法

<script type="text/javascript">
        const app = new Vue({
            el:'#app',
            data:{
                num:0
            },
            methods:{
                numChange(newValue){
                    this.num = parseInt(newValue)
                }
            },
            components:{
                cpn:{
                    template:'#cpn',
                    props:{
                        cnum:Number
                    },
                    data(){
                        return{
                            dnum:this.cnum
                        }
                    },
                    watch:{//v-model监听改变
                        //一般参数定义为newValue                        
                        dnum(newValue){
                            this.$emit('numchange',newValue)
                        }
                    }
                }
            }
        })
    </script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。