Vue组件入门

本文简单介绍一下vue中的组件相关的知识点,包括组件的概念,注册,使用,以及组件之间的通信。内容比较简单,代码内有注释,适合入门。

目录

组件的概念

组件的注册

全局组件的注册

组件的命名

全局组件的注册和使用

全局组件注册

全局组件的使用

例子

局部组件的注册以及使用

例子

局部组件的第二种注册方式

注册组件的注意事项

组件间的通信

组件间的通信解释

父给子组件传值

例子

 定义props中值的默认值和数据类型

子组件通过$emit 传递数据给父组件

 兄弟组件之间的传值

兄弟组件传值-中央事件总线

动态组件 

动态组件如何使用

 keep-alive 

基础用法

activated 和 deactivated 生命周期

include 和 exclude


组件的概念

通俗的来理解,组件就是一个功能模块。

组件是可以复用的vue的一个实例,并且带有一个名字 -- 来自官方

扩展:定义组件考虑的问题:提升组件的复用性,降低组件之间耦合性 加强内聚。

组件的注册

全局组件的注册

可以通过vue.component的方式来定义全局组件,接收两个参数,第一个参数是组件名,第二个参数是一个对象。

属性的对象:组件的属性对象为vue的实例的对象,组件就是对vue做了一个实例化

Vue.component('组件名', {})

组件的命名

1.短横线 --- <my-component-name>

2.驼峰命名 -- <myComponentName>(比较推荐驼峰命名法)

注意:使用驼峰命名的的时候,首字母最好是大写字母开头(大驼峰)

如:

Vue.component('MyComponentName', {//大驼峰命名法
    
})
Vue.component('my-component-name', {//或者短横线命名法
    
})

全局组件的注册和使用

全局组件注册

引用模板template内为模板字符串,存放你要渲染的dom结构和相关数据。推荐使用反引号+dom结构,统一规范。

Vue.component('myComponent', {
    // 添加模板 -- 模板一定要有唯一的一个根元素
    //模板字符串一般使用es6里面的反引号,统一规范
    template: `
    <div>
        hello
    </div>
    `
})

全局组件的使用

全局组件可以在项目中的任何位置被使用,使用的方式就是标签的使用方式

注意把驼峰命名法里面的大写变小写,并用短横线连接起来

双闭合后面可以使用组件,但是单闭合不可以

如单标签,双标签(双标签内还可以写东西):

<my-component-name />//单标签写法
<my-component-name></my-component-name>//双标签写法

例子

把hello渲染到页面上。

我们定义一个组件名为MyComponent,在函数内写了模板字符串,div内写hello。在div内使用双标签的方式使用这个组件。就可以成功在页面上渲染hello。

<div id="app">
        <my-component></my-component>
    </div>
//全局组件
        Vue.component('MyComponent',{//大写的Vue,这个组件就相当于一个实例
            //使用组件的时候,就把大写字母变小写,使用-拼接,类似标签一样使用
            //字符串模板必须要有唯一的根元素
            template:`
            <div>
                hello
            </div>
            `
        })
         let vm = new Vue({
            el: '#app',
            data: {
                msg: 'aaa',
            }
        })

局部组件的注册以及使用

局部组件与全局组件相似,但它需要在根组件中注册 使用components写在Vue实例里面。它与methods,data等是同级的兄弟关系。

例子

把hello渲染到页面上。

与全局组件相似,但是写在了Vue实例的components里面。

<div id="app">
        <my-component></my-component>
    </div>
let vm = new Vue({
            el: "#app",
            data: {
 
            },
            methods:{
 
            },
            components: {
                'myComponent': {
                    template: `
                <div>
                    hello
                </div>
                `
                }
            }
        })

局部组件的第二种注册方式

我们可以单独把局部组件的注册代码注释掉,自己单独写一个对象,对象中含有data数据,template标准字符串等,再把它赋值给一个变量,把这个变量拿到Vue实例的components中,同样可以实现局部组件的注册。

var helloWord={//声明一个变量helloWord,赋值一个对象
            data:function(){//data是个函数
                return{
                    msg:'helloword'//返回值为字符串helloword
                }
            },
            methods:{
 
            },
            //渲染,div内用差值表达式渲染msg的数据
            template:`
                <div>
                    {
   
   {msg}}
                </div>
                `
        }
        //组件就是一个功能模块
        //局部组件
        let vm = new Vue({
            el: '#app',
            data: {
                msg: 'aaa',
            },
           components:{//局部组件的注册
            // 'MyComponent':{
            //     template:`
            //     <div>
            //         hello
            //     </div>
            //     `
            // }
            helloWord//把helloWord这个对象拿过来,相当于替代了上面被注释掉的局部组件的注册
           }
        })

注册组件的注意事项

- 组件模板内容(template内)必须是单个根元素,也就是只有一个根元素

- 组件模板内容可以是模板字符串 -- 是用反引号

- 模板字符串需要浏览器支持(es6中的语法,所以浏览器得兼容es6)

- data必须是一个函数,data:{} // 其实在运行的时候,是函数的调用

组件间的通信

组件间的通信解释

组件之间是独立的,不同组件之间的数据是无法相互引用的,需要使用特定的方式来实现数据的通用

父给子组件传值

父组件通过props属性向子组件传递数据,子组件利用组件的实列props属性定组件需要接收的参数

在父组件中使用子组件,把需要传的值,以属性的方式绑定到子组件上

在子组件中使用 props属性接收这个值 数组中使用引号把属性名引起来,多个属性之间使用逗号隔开

例子

 <div id="app">
        <parent></parent>
    </div>
// 定义parent组件
        Vue.component('parent', {
            //在template中把组件child的name和age渲染出来
            //把父组件中需要专递的值,以属性的方式绑定到子组件上
            template: `
            <child :name="name" :age="age" />//在父组件中使用子组件
            `,
            data: function () {//定义data函数,以对象的形式返回name和age的值
                return {
                    name: '王大爷',
                    age: 22
                }
            }
        })
        // 定义 child 组件
        Vue.component('child', {
            //在子组件中使用props的方式接收传递过来的值
            props: ['name', 'age'],//在props属性接受父组件name和age的值
            //渲染,div中的name和age
            template: `
            <div>{
   
   {name}}{
   
   {age}}</div>
            `
        })
        let vm = new Vue({
            el: '#app',
            data: {
                msg: 'aaa',
            },
           components:{//局部组件的注册
          
           }
        })

结果:渲染出数据如下

步骤总结

1、定义一个父组件和一个子组件

2、在父组件中使用子组件

3、把父组件中需要专递的值,以属性的方式绑定到子组件上

4、在子组件中使用props的方式接收传递过来的值

 定义props中值的默认值和数据类型

父给子组件传值,props接收数据的方式,就应该把数组的方式,变为对象的方式

所以我们尝试把parent组件内的data函数注释了,在child组件内添加props的数据,和数据类型的约束,以对象的形式。

 // 定义parent组件
        Vue.component('parent', {
            //在template中把组件child的name和age渲染出来
            template: `
            <child :name="name" :age="age" />
            `,
             data: function () {//定义data函数,以对象的形式返回name和age的值
                return {
                    name: '王大爷',
                    age: 22
                }
            }
        })
 
        // 定义 child 组件
        Vue.component('child', {
        //添加props的数据,和数据类型的约束,以对象的形式
            props: {
                name: {
                    type: String,
                    default: '二大爷'
                },
                age: {
                    type: Number,
                    default: 80
                }
            },
            //渲染,div中的name和age
            template: `
            <div>{
   
   {name}}{
   
   {age}}</div>
            `
        })
        let vm = new Vue({
            el: '#app',
            data: {
                msg: 'aaa',
            },
            components: {//局部组件的注册
 
            },
 
        })

结果:

所以在渲染页面的时候,name和age数据由child组件的props给出默认值,parent组件内的定义的data函数给出数据可以去覆盖这个默认值。

子组件通过$emit 传递数据给父组件

 //其实就是子组件去获取了父组件的值,对这个值进行了操作,并不是去直接改变父组件的数据
        //其实可以通过子组件去修改父组件的数据,但其数据发生改变,父组件向多个子组件传值,这些子组件的值都要发生改变,所以我们不可以使用这个办法
        // 定义parent组件
        Vue.component('parent', {
            //把$emit自定义的事件函数age-add拿过来用,并且把methods内定义的函数内获取的age值拿给age-add操作
            //在template中把组件child的name和age渲染出来,age-add操作完age值后,会改变age值,在页面上渲染出来
            template: `
            <child :name="name" :age="age" @age-add="age_data" />
            `,
            methods: {
                //这个函数用来拿取data内的age数据
                age_data(age) {
                    this.age = age
                }
            },
            data: function () {
                return {
                    name: '王大爷',
                    age: 22
                }
            }
        })
 
        // 定义 child 组件
        Vue.component('child', {
            //使用props拿取父元素的数据
            props: ['name', 'age'],
            //template内的dom节点内,按钮应用add方法实现age的点击自增
            template: `
            <div>
                {
   
   {name}}{
   
   {age}}
                <button @click="add">按钮</button>
            </div>
            `,
            methods: {
                add: function () {
                    //在子组件中使用$emit(事件名,数据) 触发一个自定义事件,事件名自定义。
                    //事件名推荐使用小写和短横线
                    this.$emit('age-add', this.age + 1)
                }
            }
        })
        let vm = new Vue({
            el: '#app',
            data: {
                msg: 'aaa',
            },
            components: {//局部组件的注册
 
            },
 
        })

 结果:

点击按钮实现自增 

 兄弟组件之间的传值

兄弟组件之间的通信,可以通过父组件为中继站,来实现。简而言之就是把父传子组件和子传父组件结合在一起。

 // 定义parent组件
        Vue.component('parent', {
            //把$emit自定义的事件函数age-add拿过来用,并且把methods内定义的函数内获取的age值拿给age-add操作
            //在template中把组件child的name和age渲染出来,age-add操作完age值后,会改变age值,在页面上渲染出来
            template: `
            <div>
                <child :name="name" :age="age" @age-add="age_data" />
                <child1 :name="name" :age="age"/>
            </div>
            `,
            methods: {
                //这个函数用来拿取data内的age数据
                age_data(age) {
                    this.age = age
                }
            },
            data: function () {
                return {
                    name: '王大爷',
                    age: 22
                }
            }
        })
 
        // 定义 child 组件
        Vue.component('child', {
            //使用props拿取父元素的数据
            props: ['name', 'age'],
            //template内的dom节点内,按钮应用add方法实现age的点击自增
            template: `
            <div>
                {
   
   {name}}{
   
   {age}}
                <button @click="add">按钮</button>
            </div>
            `,
            methods: {
                add: function () {
                    //在子组件中使用$emit(事件名,数据) 触发一个自定义事件,事件名自定义。
                    //事件名推荐使用小写和短横线
                    this.$emit('age-add', this.age + 1)
                }
            }
        })
         // 定义 child1 组件
         Vue.component('child1', {
            //使用props拿取父元素的数据
            props: ['name', 'age'],
            //template内的dom节点内
            template: `
            <div>
                {
   
   {name}}{
   
   {age}}
            </div>
            `,
        })
        let vm = new Vue({
            el: '#app',
            data: {
                msg: 'aaa',
            },
            components: {//局部组件的注册
 
            },
 
        })

兄弟组件传值-中央事件总线

我们可以利用vue的原型对象,把兄弟组件的数据想办法挂载到原型对象上,由其他组件拿取。

主要是利用$emit和$on自定义事件,来传输数据和拿取数据。

定义事件总线 
let bus = new Vue() 
Vue.prototype.a = bus

定义发送的事件
this.a.$emit('事件名称', data)

定义接收事件 并在回调函数中接收参数
this.a.$on('事件名称', (data) => {  })

上代码,内有详细注释:

 <div id="app">
        <person></person>
        <detail />
    </div>
    /* 
       // 定义事件总线 
       let bus = new Vue() 
       Vue.prototype.a = bus
       // 定义发送的事件
       this.a.$emit('事件名称', data)
       // 定义接收事件 并在回调函数中接收参数
       this.a.$on('事件名称', (data) => {  })
               
       */
 
        // 逻辑代码
        let bus = new Vue()//创建一个vue实例
        Vue.prototype.bus = bus//把这个vue实例挂载到vue的原型对象上
        //相当于把person内的数据,挂载到vue的原型对象上,供其他兄弟组件拿取,主要是$emit和$on自定义事件的使用
        Vue.component('person', {
            template: `
            <div>
                <div>姓名:<input type="text" v-model="name"></div>
                <div>年龄:<input type="text" v-model="age"></div>
                <button @click="midfiy">修改</button>
            </div>
            `,
            methods: {
                //定义midfiy方法,用bus实例和$emit自定义事件,拿取data里面的name和age,相当于把数据存放到bus里面,挂载到vue的原型对象里面
                midfiy() {
                    this.bus.$emit('midfiy', { name: this.name, age: this.age })
                }
            },
            data() {
                return {
                    name: '张三',
                    age: 20
                }
            }
        })
        Vue.component('detail', {
            template: `
            <div>
                我是: {
   
   {name}},
                我今年:{
   
   {age}} 岁了
            </div>
            `,
            data() {
                return {
                    name: '李四',
                    age: 18
                }
            },
            mounted() {//使用声明周期函数内的mounted
                //使用bus和$on自定义一个事件,用来拿取存放在bus内的,person组件内的数据,并且把数据赋值给detail组件内data的数据
                this.bus.$on('midfiy', (detail) => {
                    this.name = detail.name
                    this.age = detail.age
                })
            }
        })
        let vm = new Vue({
            el: "#app",
            data: {
 
            }
        })

结果:

刚打开页面,detail组件会拿取自己data里面的默认数据。

 点击按钮后,detail组件就会拿取person组件内的数据

动态组件 

动态组件就是让多个组件使用同一个挂载点,并实现动态切换

动态组件如何使用

通过使用保留的<compionent>元素,动态的把组件名称绑定到  is  特性上 可以实现动态组件

代码如下

<div id="app">
        <!-- 通过使用保留的<compionent>元素,动态的把组件名称绑定到  is  特性上 可以实现动态组件 -->
        <component :is="currentView"></component>
        <!-- 为三个按钮设置点击事件changeView('A'),并为其传参A,B,C -->
        <button @click="changeView('A')">切换到A</button>
        <button @click="changeView('B')">切换到B</button>
        <button @click="changeView('C')">切换到C</button>
    </div>
//定义组件A,B,C
        Vue.component('componentA', {
            template: `<div>组件A</div>`,
 
        })
 
        Vue.component('componentB', {
            template: `<div>组件B</div>`
        })
 
        Vue.component('componentC', {
            template: `<div>组件C</div>`,
 
        })
 
        let vm = new Vue({
            el: "#app",
            data() {
                //在data中定义默认组件currentView,并且赋值默认值
                return {
                    currentView: 'componentB' // 显示默认组件
                }
            },
            methods: {
                //点击事件的函数,获取传递的参数
                changeView: function (name) {
                    //为currentView重新赋值,值为字符串拼接成组件名字
                    this.currentView = `component${name}`
                }
            }
        })

结果如下

 keep-alive 

是vue提供的一个抽象组件用来对组件进行缓存,从而节省性能

基础用法

结合上面动态组件如何使用模块的代码,如下

<keep-alive>
    <component :is="currentView"></component>
</keep-alive>

activated 和 deactivated 生命周期


activated 和 deactivated 和之前的生命周期函数是一样的,这两个只是在 <keep-alive> 内的所有嵌套的组件中触发

activated : 进入组件的时候触发

deactivated :退出组件的时候触发

代码如下,直接在原来代码上添加

Vue.component('componentA', {
    template: `<div>组件A</div>`,
 
    activated(){
        console.log('进入A');
    },
    deactivated(){
        console.log('退出A');
    }
})

结果:

当我们点击A的时候,打印'进入A',当我们点击别的按钮,就会打印'退出A'。

include 和 exclude

是keep-alive的属性,允许组件有条件的缓存

include :可以是字符串或者正则表达式,用来表示只有名称匹配的组件会被缓存

exclude :可以是字符串或者正则表达式,用来表示只有名称匹配的组件不会被缓存

使用方法如下

include

<keep-alive include="componentA,componentB">
    <component :is="currentView"></component>
</keep-alive>

exclude

<keep-alive exclude="componentA,componentB">
    <component :is="currentView"></component>
</keep-alive>

结合例子来看:

//定义组件A,B,C
        Vue.component('componentA', {
            template: `<div>组件A</div>`,
            created() {
                console.log('显示组件A');
            }
        })
 
        Vue.component('componentB', {
            template: `<div>组件B</div>`,
            created() {
                console.log('显示组件B');
            }
        })
 
        Vue.component('componentC', {
            template: `<div>组件C</div>`,
            created() {
                console.log('显示组件C');
            }
 
        })

结果:

在频繁点击下,c只会被打印一次,而a,b被多次打印,因为我们exclude设置 组件a,b不应用缓存,而c保持默认设置使用缓存

猜你喜欢

转载自blog.csdn.net/zhangawei123/article/details/129202875
今日推荐