Vue2(六):组件化编程

Vue组件化编程

一、使用组件的三大步

1、定义组件(创建组件)
2、注册组件
3、使用组件(写组件标签)

1.如何定义一个组件?

使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:

(1)el不要写,为什么?
最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。备注:使用template可以配置组件结构。

(2)data必须写成函数,为什么?
避免组件被复用时,数据存在引用关系,比如我父组件要多次复用一个子组件,那如果其中一个子组件做了修改数据操作,其他复用的地方数据也会被修改。看看下面的代码,就明白了

   //1.data定义为对象,里面的值有人一改,那全都用到底地方都改了
    let data = { a: 1, b: 2 };
    let x = data;   //如果x.a = 10 ,那么y也会变成{ a: 10, b: 2 }
    let y = data;

    //2.data定义为函数,里面的值有人改,其他用到的地方不变(每次用到都会返回一个全新的)
    let data1 = function () {
        return { a1: 1, b1: 2 };
    }
    let x1 = data1();  //如果x1.a1=10,那么y1还是{ a1: 1, b1: 2 }
    let y1 = data1();

如果某个组件中的data写成对象形式,且组件内有对数据的操作,那么该组件在多次复用时,每次点击某一个按钮,其他组件实例的数据都会改变,所以这样是不行的

2.如何注册组件?

(1)局部注册
   <!-- 准备一个容器 -->
    <div id="root">
        <xuexiao></xuexiao>
        <hr>
        <xuesheng></xuesheng>
    </div>

    <script>
        //第一步:创建school组件
        const school = Vue.extend({
        	name: 'dj', //可以使用name配置项指定组件在开发者工具中呈现的名字(只是开发者工具里用的名字)。
            // el: '#hello'  el不能写
            template: `
                <div>
                    <h2>学校名字{{schoolName}}</h2>
                    <h2>学校地址{{address}}</h2>
                </div>
            `,
            data() {
                return {
                    schoolName: 'web',
                    address: '杭州',
                }
            }
        })

        //第一步:创建student组件
        const student = Vue.extend({
            template: `
                <div>
                    <h2>学生名字{{studentName}}</h2>
                    <h2>学生年龄{{age}}</h2>
                    <button @click="add">点击年龄+1</button>
                </div>
            `,
            data() {
                return {
                    studentName: 'zzy',
                    age: 18
                }
            },
            methods: {
                add() {
                    this.age++;
                }
            },
        })

        //创建一个vm带领小弟接管root容器
        const vm = new Vue({
            el: '#root',
            // 第二步:注册组件(局部注册)
            components: {
                //组件名:组件
                //这里最好写成school:school,简写为school
                xuexiao: school,
                //这里最好写成student:student,简写为student
                xuesheng: student
            }
        })
    </script>

(2)全局注册

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

   <!-- 准备一个容器 -->
    <div id="root">
        <sayhello></sayhello>
    </div>

    <!-- 准备第二个容器 -->
    <div id="root2">
        <sayhello></sayhello>
    </div>

    <script>
        //第一步:创建组件
        const hello = Vue.extend({
            template: `
                <div>
                    <h2>{{msg}}</h2>
                </div>
            `,
            data() {
                return {
                    msg: 'hello world'
                }
            }
        })
        //第二步:全局注册组件
        Vue.component('sayhello', hello);

        //创建第一个vm接管root
        const vm = new Vue({
            el: '#root'
        })

        //创建第二个vm接管root2
        new Vue({
            el: '#root2'
        })
    </script>

3.使用组件

直接写组件名的标签就欧了,一般我们定义组件时,组件名和定义的名字最好一样,这样就可以简写。(详见2.(1)代码中的注释)

   <!-- 准备一个容器 -->
    <div id="root">
        <xuexiao></xuexiao>
        <xuesheng></xuesheng>
    </div>

二、使用组件的一些注意点

1.关于组件名:

一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School
多个单词组成:
第一种写法(kebab-case命名):‘my-school’
第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
备注:
(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字(不影响注册的名字)。

2.关于组件标签:

第一种写法:<school></school>
第二种写法:<school/>
备注:不用使用脚手架时,<school/>会导致后续组件不能渲染。

3.一个简写方式:

const school = Vue.extend(options)` 可简写为:const school = options

三、组件的嵌套

这里要注意,vm里要写el,其他都不写。vm里的template可以不用写根节点,因为vm里的东西是放到容器里的,而组件的template要用根节点包起来(如div)。这块儿就是一直套娃(代码倒着看)

在这里插入图片描述

<body>
    <div id="root">
        <app></app>
    </div>
</body>
<script>

    // 定义student组件
    const student = Vue.extend({
        name: 'student',
        template: `
            <div>
				<h2>学生名称:{{name}}</h2>	
				<h2>学生年龄:{{age}}</h2>	
			</div>
        `,
        data() {
            return {
                name: 'czy',
                age: '18'
            }
        }
    })
    // 定义school组件
    // const school = Vue.extend({
    //     name: 'school',
    //     template: `
    //         <div>
    // 			<h2>学校名称:{{name}}</h2>	
    // 			<h2>学校地址:{{address}}</h2>	
    // 		</div>
    //     `,
    //     data() {
    //         return {
    //             name: 'Kiwi233',
    //             address: '湖南湘潭'
    //         }
    //     },
    //     components: {
    //         student
    //     }
    // })
    const school = Vue.extend({
        // el: '#hello'  el不能写
        template: `
            <div>
                <h2>学校名字{{schoolName}}</h2>
                <h2>学校地址{{address}}</h2>
                <student></student>
            </div>
        `,
        data() {
            return {
                schoolName: 'hnust',
                address: '湖南湘潭',
            }
        },
        //第三步,注册局部组件
        components: {
            //第四步,局部组件放入当前组件模板
            student
        }
    })

    const hello = Vue.extend({
        template: '<h2>{{msg}}</h2>',
        data() {
            return {
                msg: '欢迎学习Vue!'
            }
        }
    })

    const app = Vue.extend({
        template: `
            <div>
                <hello></hello>
                <school></school>
            </div>
        `,
        components: {
            school,
            hello
        }
    })

    new Vue({
        el: '#root',
        // 注册组件(局部)
        components: {
            app
        }
    })
</script>

四、VueComponent构造函数

school组件是一个Vue.extend生成的构造函数,当组件写到页面上时,Vue开始解析,同时自动搞了个new,这才创建了school组件的实例对象

1.什么是VueComponent?

1、school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。

2、我们只需要写<school/><school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)

3、特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent构造函数而不是返回VueComponent的实例(这个地方不要陷入误区),只有当Vue解析组件时,才会返回所对应组件(如school)的VueComponent的实例对象

2.VueComponent中的this指向

VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。Vue的实例对象,以后简称vm。

(1)组件配置中
  • data函数、methods中的函数、watch中的函数、computed中的函数。它们的this均是【VueComponent实例对象】

  • 我这么理解,school组件是一个Vue.extend生成的构造函数,然后在这个extend里鱿鱼西还搞了个自动生成new,所以在页面使用组件时(Vue解析组件标签时)就顺便儿创建了school组件的实例对象,所以this指向Vc

(2)new Vue(options)配置中
  • data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】

3.组件实例和Vue实例

其实这俩就像一对儿双胞胎,东西基本上99%都一样,但是这俩人不能划等号,还是有点小小的区别的,比如组件里不能写el组件里data必须写成函数。vc有的vm都有,但是vm可以用el决定操作谁

4.一个重要的内置关系

这块儿听懂了,但是还差点事儿,这个图可以结合pink老师的图去理解,js高级抽空儿得补补。
1、一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype

2、为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

在这里插入图片描述

五、单文件组件

1.School.vue

<template>
    <!-- 组件的结构 -->
    <div>
        <h2 class="demo">学校名字{{ name }}</h2>
        <h2>学校地址{{ address }}</h2>
    </div>
</template>

<script>
// 组件交互相关的代码(数据,方法等等)
export default {
    name: 'School',
    data() {
        return {
            name: 'web',
            address: '杭州',
        }
    }
}

//等价于下面的代码
// const School = Vue.extend({
//     name: 'School',
//     data() {
//         return {
//             name: 'web',
//             address: '杭州',
//         }
//     }
// })

// export default School;
</script>

<style>
/* 组件的样式 */
.demo {
    background-color: pink;
}
</style>

2.Student.vue

<template>
    <!-- 组件的结构 -->
    <div>
        <h2>学生名字{{ name }}</h2>
        <h2>学生年龄{{ age }}</h2>
    </div>
</template>

<script>
// 组件交互相关的代码(数据,方法等等)
export default {
    name: 'Student',
    data() {
        return {
            name: 'zzy',
            age: 18
        }
    },
}

//等价于下面的代码
//  const Student = Vue.extend({
//     name: 'Student',
//     data() {
//         return {
//             name: 'zzy',
//             age: 18
//         }
//     },
// })

// export default Student;
</script>

3.App.vue

<!-- vueInit按回车快捷键生成 -->
<template lang="">
    <div>
        <School></School>
        <Student></Student>
    <Student/>
    <Student/>
    <Student/>
    </div>
</template>
<script>
//引入组件
import School from './School.vue'
import Student from './Student.vue'

export default {
    name: 'App',
    components: {
        School,
        Student
    }
}
</script>
<style lang="">
    
</style>

4.main.js

import App from './App.vue'

new Vue({
    el: '#root',
    components: { App }
})

5.index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>练习单文件组件的语法</title>
</head>
<body>
    <div id="root">
        <App></App>
    </div>
    <script src="../vue.js/vue.js"></script>
    <script src="./13.main.js"></script>
</body>
</html>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值