VUE组件化基础知识

============================================================

component(组件)

ES6新语法:

`在这里写字符串可以直接换行`(tab上面的键)

组件最基本的使用:
1、创建组建构造器对象
2、注册组件
3、使用组件

组件化开发体验:

template 后面要接字符串

Vue.component(‘自定义标签名’,组件构造器对象名),
注册的是全局组件,意味着可以在多个vue的实例下面使用

<body>
    <div id="app">
            <my_cpn></my_cpn>
    </div>
    <div id="app1">//不在这个实例内部注册所以不能调用
            <my_cpn></my_cpn>
</div>
    
    <script>
        //1、创建组件构造器对象
        const cpnc=Vue.extend({
            template : `
            <div>
                <h2>我是标题</h2>
                <p>我是内容,5555</p>
                <p>我也是内容,88888</p>
            </div>        
            `
        })

        //2、注册组件(全局组件)
        // Vue.component('my_cpn',cpnc)

        const vm=new Vue({
            el:'#app',
            data:{
                message:'dfsdfdsfds'
            },
            components:{//要加s
                my_cpn:cpnc
            }//注册局部组件

        })

        const vm2=new Vue({
            el:'#app1',
        })
    </script>
</body>

子组件和父组件:

<body>
    <div id="app">
            <my_cpn></my_cpn>
    </div>
</div>
    
    <script>
        //1、创建组件构造器对象
        const cpnc1=Vue.extend({//子组件
            template : `
            <div>
                <h2>我是标题</h2>
                <p>我是内容,5555</p>
                <p>我也是内容,88888</p>
            </div>        
            `
        })

        const cpnc2=Vue.extend({//父组件
            template : `
            <div>
                <h2>我是标题2</h2>
                <p>我是内容22222</p>
                <p>我也是内容22222222</p>
                <diy></diy>
            </div>        
            `,
            components:{//因为第一个组件注册在了第二个组件构造器里面
                diy:cpnc1
            }
        })

        //2、注册组件(全局组件)
        // Vue.component('my_cpn',cpnc)


		//root,根组件
        const vm=new Vue({
            el:'#app',
            data:{
                message:'dfsdfdsfds'
            },
            components:{
                my_cpn:cpnc2
            }//注册局部组件

        })

    </script>
</body>

注册组件的语法糖:推荐使用
1、Vue为了简化这个过程,提供了注册的语法糖
2、主要省去了调用Vue.extend()的步骤,但是vue源码内部还是会使用extend方法,
而是可以直接使用一个对象来代替。

 const vm=new Vue({
            el:'#app',
            data:{
                message:'dfsdfdsfds'
            },
            components:{
                my_cpn:{
                            template : `
                            <div>
                                <h2>我是标题2</h2>
                                <p>我是内容22222</p>
                                <p>我也是内容22222222</p>
                                <diy></diy>
                            </div>        
                            `,
                        }
            }//注册局部组件语法糖写法

        })

template分离写法:

1、使用<template id="cpn2"></template>标签

  <template id="cpn2">
           <div>
                    <h2>我是标题2</h2>
                    <p>我是内容22222</p>
                    <p>我也是内容22222222</p>
                    <diy></diy>
                </div>        
    </template>
    <script>

        //2、注册组件(全局组件)
        // Vue.component('my_cpn',cpnc)

        const vm=new Vue({
            el:'#app',
            data:{
                message:'dfsdfdsfds'
            },
            components:{
                my_cpn:
                {
                            template : '#cpn2'
                        }
            }//注册局部组件

        })

    </script>

2、使用<script type="text/x-template" id="cpn2"></script>标签

<script type="text/x-template" id="cpn2">
           <div>
                  <h2>我是标题2</h2>
                   <p>我是内容22222</p>
                   <p>我也是内容22222222</p>
                   <diy></diy>
               </div>        
    </script>
    <script>

        //2、注册组件(全局组件)
        // Vue.component('my_cpn',cpnc)

        const vm=new Vue({
            el:'#app',
            data:{
                message:'dfsdfdsfds'
            },
            components:{
                my_cpn:
                {
                            template : '#cpn2'
                        }
            }//注册局部组件

        })

    </script>

============================================================

组件不能访问vue实例中的data:

想存放组件中的数据,最好放在组件自己的data属性中:
1、组件对象有自己的data属性(也可以有methods等属性)
2、与实例的data属性不同,组件对象的属性必须是一个函数
3、而且这个属性是函数会返回一个栈空间,栈空间内部会创建很多变量


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
为什么设计组件的data要使用函数而不是对象?
1、因为函数是会返回一个栈空间,栈空间内部会创建很多变量,每个栈空间的内存地址不一样,当数据改变时,每个组件之间不会相互影响。
2、如果使用像实例一样的对象类型的话,会导致组件指向的都是同一个内存地址,当数据发生改变时会导致连锁反应,所有组件一起变化,后果影响很大。
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


用组件化开发实现计数器的复用:

<body>
    <div id="app">
        <computed_number></computed_number>//组件的调用
        <computed_number></computed_number>
        <computed_number></computed_number>
        
    </div>
    
    <template id="cpn">//模板分离写法
        <div>//记得加上div标签封装
            <h2>计算结果:{{count}}</h2>
            <button @click="add()">+</button>
            <button @click="sub()">-</button>
        </div>
    </template>

    <script>

        //注册全局组件
        Vue.component('computed_number',{//用逗号
               template:'#cpn',//用template绑定模板ID
                data(){
                 return{//组件内部的data必须是函数,且值是返回值
                     count:0
                 }
                },
                methods: {//组件内部的方法
                    add(){
                        this.count++
                    },
                    sub(){
                        this.count--
                    }
                }, 
                
        })

        const vm=new Vue({
            el:'#app',
     
        })
    </script>
</body>

===============================================================

父子组件之间的通信:
在这里插入图片描述

1、通过props向子组件传递数据
2、通过事件向父组件发送消息

常用写法:

props:['cmovies']

//props是属性properties的简写,里面的是变量,用于接收父组件的数据


    props:{
     cmovies:Array}
     //写成对象类型,可以进行类型验证

props:{
		comvies:{
		type:String,
		default:’aaa‘,
		required:true}//required:属性为true时要传进来值才能用
			}
		//当传入类型时字符串时可以直接写默认值
		comvies:{
		type:Array,
		default(){
		return [ ]
		}}
		//但是当数据类型是对象或者数组时,默认值必须是一个函数	
	//把接收值也写成对象类型,可以设置未处理时默认值
	// !!!当传入类型时字符串时可以直接写默认值,但是当数据类型是对象或者数组时,默认值必须是一个函数	

================================================================
以根组件为父组件,实现数据的传递:

<body>
    <div id="app">
        <mycpn  :cmovies='movies'></mycpn>//外层绑定数据
    </div>
    
    <template id="mytemp"> 
        <div>
            <ul>
                <li v-for="item in cmovies">{{item}}</li>
                //模板写逻辑
            </ul>
        </div>

    </template>

    <script>

     const  cpn ={
         template:'#mytemp',
         //props:['cmovies']//props是属性properties的简写,里面的是变量,用于接收父组件的数据
         //props:{
         //cmovies:Array//写成对象类型,可以进行类型验证
		//}
		props:{
			comvies:{
			type:String
			default:’‘//把数据也写成对象类型,可以设置未处理时默认值
			}
		
		}

        const vm=new Vue({
            el:'#app',
            data:{
                movies:['海贼王','海尔兄弟','海天堂','海王','海的味道']
            },
            components:{//记得加S
                'mycpn':cpn
            }
        })
    </script>
</body>

props更多写法:
在这里插入图片描述

===================================================================

父传子(props中的驼峰标识):
//当使用驼峰标识的时候要将大写字母改小写并且加上-。

写模板的时候要使用外层div包起来

<body>
    <div id="app">
        <submessage :sub-message="message"></submessage>
        //当使用驼峰标识的时候要将大写字母改小写并且加上-
    </div>
    

    <template id="submessage"> 
        <div>
            <h2>{{subMessage}}</h2>
        </div>
    </template>
    <script>

        const SB={
            template:'#submessage',
            props:{
                subMessage:{//这里就是需要绑定值的地方
                    type:Object,
                    default(){
                        return{}
                    }
                }
            }
        }

        const vm=new Vue({
            el:'#app',
            data:{
                message:{
                   name:'小李',
                   age:'18',
                   height:175
                }
            },
            components:{

                'submessage':SB
            }
        })
    </script>
</body>

====================================================================

组件通信:子传父:
categories(类别的意思)
$emit(发射的意思)

在这里插入图片描述


子传父:按钮例子
在这里插入图片描述
看注释:

<body>
    <div id="app">
        <btntest @diy-click="show"></btntest>//通过监听子组件的事件是否触发,来调用函数show,默认会传子组件发射的值,没有浏览器的event值
    </div>
    

    <template id="jingdong">
        <div>
            <button v-for="item in categories" @click="diyclick(item)">{{item.name}}</button>//模板接收到点击事件会触发diyclick(item)函数
        </div>
        
    </template>
    <script>

        const SB={
           template:'#jingdong',
           data(){//自组件的数据
               return{
                    categories:[
                        {id:'111',name:'热门推荐'},
                        {id:'222',name:'数码产品'},
                        {id:'333',name:'母婴产品'},
                        {id:'444',name:'床上用品'}
                        ]
               }
           },
           methods:{
               diyclick(item){
                   this.$emit('diy-click',item)
                   //模板因事件调用函数后会发射个自定义事件'diy-click',以及数据item
               }
           }
        }


        const vm=new Vue({
            el:'#app',
            data:{
            },
            components:{
                'btntest':SB
            },
            methods:{
                show(item){//最后被调用弹出item.name
                    alert(item.name)
                }
            }
        })
    </script>
</body>

===================================================================

模板内使用双向绑定v-model的时候不要直接绑定props的值,
因为还没赋值,要绑定注册子组件内data()的值

在这里插入图片描述

父子双向绑定实例:
看注释:

<body>
    <div id="app">
        <shuangxiang :number1="num1"
                     :number2="num2" 
        @numchange1="fathernumchange1" 
        @numchange2="fathernumchange2">//监听子组件发射的事件
        </shuangxiang>
        <p>结果1父data:{{num1}}</p>
        <p>结果2父data:{{num2}}</p>
    </div>

    <template id="cmodel">
        <div>
            <p>结果1props:{{newnumber1}}</p>
            <input type="text"  :value="newnumber1" @input="numinput1">//这里要拆分v-model来获取event值
            <p>结果2props:{{newnumber2}}</p>
            <input type="text" :value="newnumber2" @input="numinput2">

        </div>    
    </template>

    <script>


        const vm=new Vue({
            el:'#app',
            data:{
                num1:0,
                num2:1
            },
            methods:{
                fathernumchange1(value){
                    this.num1=parseInt(value)//要把结果进行类型转换
                },
                fathernumchange2(value){
                    this.num2=parseInt(value)//一样
                }

            },

            components:{
                'shuangxiang':{
                    template:'#cmodel',
                    props:{
                        number1:Number,//第二个值只是限制类型的作用,这里相当于声明
                        number2:Number
                    },
                    data(){//记得要用data重新做一次赋值,否则会报错
                        return{
                             newnumber1:this.number1,
                             newnumber2:this.number2
                        }
                      
                    },
                    methods: {
                        numinput1(event){
                            this.newnumber1=event.target.value
                            this.$emit('numchange1',this.newnumber1)
                            //当模板中监听到input事件时获取他的value,且发射一个事件给父组件来修改父组件的data值
                        },
                        numinput2(event){
                            this.newnumber2=event.target.value
                            this.$emit('numchange2',this.newnumber2)
							//当模板中监听到input事件时获取他的value,且发射一个事件给父组件来修改父组件的data值
                        }
                    },

                }

                }
            })
    </script>
</body>

逻辑图:
在这里插入图片描述


父子组件的访问方式:
1、$children [index] 直接获取index所在的子组件,不常用
2、$refs 可以通过类似id一样给子组件赋一个ref=“”值来实现单独获取,常用90%
3、$parent 直接获取父组件数据,不常用
3、$root 直接获取根组件vue实例的数据,不常用

用法类似,调用时直接类似 this.$root.name
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值