十四天学会Vue——Vue 组件化编程(理论+实战)(第四天)

二、 Vue组件化编程

2.1 组件化模式与传统方式编写应用做对比:

传统方式编写应用

依赖关系混乱,不好维护:例如:比如需要引入js1,js2,js3,但是js3需要用到js1、2的方法,所以js1、2要先引入,而js2的使用需要用到js1中的方法,也就是js1需要在js2前面引用,三个我们还能分清先后顺序,可是多了就会混乱。
2.代码复用率不高
两个html,相同的底部和顶部结构,先创建html1,在创建html2时,是复制了html1的,不属于代码复用;此时,如果将相同结构包装在同一段html结构中,用innerHTML来实现代码复用,这一块我也不太明白,死记硬背吧,就是封装相同的也不好用!
请添加图片描述

使用组件化方式优势:

在这里插入图片描述
在这里插入图片描述

2.2 非单文件组件

小tips 使用函数式和对象式改变数据的方法 :
作用:通过分析函数式和对象式的区别,才能知道组件中创建组件时里面的data数据使用函数式的原因了。同一个data数据,但是调用时有不同的实例 互相不会干扰

 // 使用对象式和函数式的区别
        // let data = {
        //     a: 1,
        //     b: 2
        // }
        function data () {
            return {
                a: 1,
                b: 2
            }
        }
        // 使用对象式一变都变 根据栈堆存放
        // const x1 = data
        // const x2 = data
        // 当你使用函数来返回对象时,每次调用该函数都会创建一个新的对象实例。即使这些对象具有相同的结构和初始值,
        //它们也是不同的对象,存储在内存的不同位置。因此,修改一个对象不会影响其他通过该函数创建的对象。
        const x1 = data()
        const x2 = data()

> > Vue中使用组件的三大步骤:
> > 					一、定义组件(创建组件)
> > 					二、注册组件
> > 					三、使用组件(写组件标签)  	
>  一、如何定义一个组件?
> >  						使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,
> 但也有点区别:
> >   				1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器
> > 			    2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。
> > 			   备注:使用template可以配置组件结构。
> >  二、如何注册组件?
> >  				1.局部注册:靠new Vue的时候传入components选项
> >  				2.全局注册:靠Vue.component('组件名',组件) 		
> >  三、编写组件标签:<school></school>

下面这段代码主要是讲述组件标签三步骤,以及创建局部组件和全局组件。主要式在注册那一块的差别!

 <!--准备好一个容器 -->
    <div id="root">
        <h1>{{msg}}</h1>
        <hr>
        <!-- 第三步:编写组件标签 -->
        <school></school>
        <hr>
        <!-- 第三步:编写组件标签 -->
        <student></student>
        <!-- 实现复用 并且因为data函数实现改变数据互不干扰
         -->
        <school></school>
        <student></student>
    </div>
    <!-- 第二个容器使用第一个容器的组件 -->
    <div id="root2">
        <school></school>
        组件标签
        <hello></hello>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
        // 第一步:创建school组件
        const school = Vue.extend({
            // el: '#root',//组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
            template: `<div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
                <button @click='showName'>点我提示学校名</button>
                </div>
            `,
            data () {
                return {
                    schoolName: '尚硅谷',
                    address: '北京昌平',
                }
            }, methods: {
                showName () {
                    alert(this.schoolName)
                }
            },
        })
        //第一步:创建student组件
        const student = Vue.extend({
            template: `
            <div><h2>学生姓名:{{studentName}}</h2>
        <h2>学生年龄:{{age}}</h2></div>`,
            data () {
                return {
                    studentName: '张三',
                    age: 18
                }
            }
        })
        //第一步:创建hello组件
        const hello = Vue.extend({
            template: `
				<div>	
					<h2>你好啊!{{name}}</h2>
				</div>
			`,
            data () {
                return {
                    name: 'Tom'
                }
            }
        })
        //第二步:全局注册组件  组件的名字 组件的位置
        Vue.component('hello', hello)
        //第二步:注册组件(局部注册)
        new Vue({
            el: '#root',
            data: {
                msg: '你好啊'
            },
            components: {
                school,
                student
            }
        })
        new Vue({
            el: '#root2',
            components: {
                school
            }
        })

        // // 使用对象式和函数式的区别
        // // let data = {
        // //     a: 1,
        // //     b: 2
        // // }
        // function data () {
        //     return {
        //         a: 1,
        //         b: 2
        //     }
        // }
        // // 使用对象式一变都变  根据栈堆存放
        // // const x1 = data
        // // const x2 = data
        // // 当你使用函数来返回对象时,每次调用该函数都会创建一个新的对象实例。即使这些对象具有相同的结构和初始值,
        //它们也是不同的对象,存储在内存的不同位置。因此,修改一个对象不会影响其他通过该函数创建的对象。
        // const x1 = data()
        // const x2 = data()
    </script>

几个注意点

 <!--准备好一个容器 -->
    <div id="root">
        <h2>{{msg}}</h2>
        <!-- 双标签 -->
        <!-- <school></school> -->
        <!-- <School></School>  -->
        <!-- <my-school></my-school> -->
        <!-- <MySchool></MySchool> -->
        <!-- 单标签 自闭合 但是写多个只展示一个 所以建议在脚手架中适合用-->
        <school />
        <school />
        <school />
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
        //定义组件
        const s = Vue.extend({
            // 也可以组件注册为一个名字 Vue开发工具展示的一个名字  也就是给Vue开发工具那一块特意起了一个名字
            name: 'atguigu',
            template: `
				<div>
					<h2>学校名称:{{name}}</h2>	
					<h2>学校地址:{{address}}</h2>	
				</div>
			`,
            data () {
                return {
                    name: '尚硅谷',
                    address: '北京'
                }
            }
        })
        // // 使用extend定义组件简写
        // const s = {
        //     // 也可以组件注册为一个名字 Vue开发工具展示的一个名字  也就是给Vue开发工具那一块特意起了一个名字
        //     name: 'atguigu',
        //     template: `
        // 		<div>
        // 			<h2>学校名称:{{name}}</h2>	
        // 			<h2>学校地址:{{address}}</h2>	
        // 		</div>
        // 	`,
        //     data () {
        //         return {
        //             name: '尚硅谷',
        //             address: '北京'
        //         }
        //     }
        // }
        new Vue({
            el: '#root',
            data: {
                msg: '欢迎学习Vue!'
            },
            components: {
                // 第一种写法(首字母小写):school  但是Vue开发工具会默认转化为首字母大写
                school: s
                // 组件名字跟组件标签要相同
                // School: s
                // 'my-school': s
                // 在脚手架中才可以接收大驼峰命名
                // MySchool: s
            }
        })
    </script>

总结:

几个注意点:
					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

一人之下 万人之上组件app

补充知识:在模板容器中没有写代码的原理 根据生命周期原理图,给换成内部模板了
在这里插入图片描述

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

    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
        // 定义school的子组件student
        const student = Vue.extend({
            name: 'student',
            template: `
				<div>
					<h2>学生姓名:{{name}}</h2>	
					<h2>学生年龄:{{age}}</h2>	
				</div>
			`,
            data () {
                return {
                    name: '尚硅谷',
                    age: 18
                }
            }
        })
        //定义school组件
        const school = Vue.extend({
            name: 'school',
            template: `
				<div>
					<h2>学校名称:{{name}}</h2>	
					<h2>学校地址:{{address}}</h2>	
                    <student></student>
				</div>
			`,
            data () {
                return {
                    name: '尚硅谷',
                    address: '北京'
                }
            },
            components: {
                student
            }
        })
        //定义hello组件
        const hello = Vue.extend({
            template: `<h1>{{msg}}</h1>`,
            data () {
                return {
                    msg: '欢迎来到尚硅谷学习!'
                }
            }
        })
        //定义app组件  相当于所有组建的管理者 也就是vm委派给app  让app管理所有组件
        const app = Vue.extend({
            template: `
				<div>	
					<hello></hello>
					<school></school>
				</div>
			`,
            components: {
                school,
                hello
            }
        })
        //创建vm
        new Vue({
            template: `<app></app>`,
            el: '#root',
            //注册组件(局部)
            components: {
                app
            }
        })
    </script>

VueComponent

总结来说:就是VueComponent就是类比于Vue,所以有实例对象vc 在组件中this指向VueComponent实例对象,也就是组件
下面案例中涉及到组件嵌套

总结

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

						2.我们只需要写<school/><school></school>,Vue解析时会帮我们创建school组件的实例对象,
							即Vue帮我们执行的:new VueComponent(options)3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!

						4.关于this指向:
								(1).组件配置中:
						data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】
								(2).new Vue(options)配置中:
						data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】

						5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
							Vue的实例对象,以后简称vm。
  <!--准备好一个容器 -->
    <div id="root">
        <school></school>
        <hello></hello>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
        //定义school组件
        const school = Vue.extend({
            name: 'school',
            template: `
				<div>
					<h2>学校名称:{{name}}</h2>	
					<h2>学校地址:{{address}}</h2>	
                    <button @click="showName">点我提示学校名</button>
				</div>
			`,
            data () {
                return {
                    name: '尚硅谷',
                    address: '北京'
                }
            }, methods: {
                showName () {
                    // 组件中的this指向VueComponent,并且里面有Vue中的很多相似数据,进行了数据代理
                    console.log('showName', this)
                }
            }
        })
        const test = Vue.extend({
            template: `<span>哈哈哈</span>`
        })
        // 定义hello组件
        const hello = Vue.extend({
            template: `
            <div>
            <h2>{{msg}}</h2>
            <test></test>
                </div>
            `,
            data () {
                return {
                    msg: '你好啊'
                }
            }, components: { test }
        })
        // 对应的VueComponent不是同一个
        // school.a = 100
        // console.log('@', school.a)
        // console.log('#', hello.a)

        // console.log('@', school)
        // console.log('#', hello)

        const vm = new Vue({
            el: '#root',
            components: {
                school, hello
            }
        });
    </script>

补充知识:上文提到望函数中添加属性,直接函数点属性名即可,因为函数在某种意义上也是对象。

 <SCRIPT>
        function aa () {
            console.log('哈哈哈')
        }
        aa.b = 100
        // 函数本身也是一个对象
        console.log(aa.b);
    </SCRIPT>

一个重要的内置关系

1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
				2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
<div id="root">
        <!-- 相当于new Component() -->
        <school></school>
    </div>
    <script>
        Vue.prototype.x = 99
        //定义school组件
        const school = Vue.extend({
            template: `
				<div>
					<h2>学校名称:{{name}}</h2>	
					<h2>学校地址:{{address}}</h2>	
                    <button @click='showX'>点我发现我能get到Vue原型对象中的x</button>
				</div>`,
            data () {
                return {
                    name: '尚硅谷',
                    address: '北京'
                }
            }, methods: {
                showX () {
                    console.log(this.x)
                }
            }
        })
        //创建一个vm
        const vm = new Vue({
            el: '#root',
            data: {
                msg: '你好'
            }, components: {
                school
            }
        })
        // 不要写VueComponent  死记硬背:我们通过调用extend函数返回值VueComponent并且赋值给school  
        //这里按理说应该是true  但是不知道怎么回事是false
        console.log(school.prototype._proto_ === Vue.prototype)

        /*  function Demo () {
             this.a = 1
             this.b = 2
         }
         //创建一个Demo的实例对象
         const d = new Demo()
         console.log(Demo.prototype) //显示原型属性
         console.log(d.__proto__) //隐式原型属性
         // 指向同一个原型对象
         console.log(Demo.prototype === d.__proto__)
         //程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
         Demo.prototype.x = 99
         // console.log('@', d._proto_.x)
         // 缩写
         console.log, ('@', d.x)
         // 表示关于demo函数的实例对象
         console.log(d); */
    </script>

组件实例对象小型vm 他的data必须写成函数式,也不能配置el

2.3 单文件组件

首先是xxx.vue,不能直接展示在浏览器,需要编译成js文件
方法1:使用webpack
方法2:使用脚手架
命名类似于组件名称 推荐首字母大写或者大驼峰命名
安装插件 识别vue文件
在这里插入图片描述

vue文件的编写依据组件的定义:实现应用中局部功能的代码和资源的集合,包括html结构、css样式、js交互

书写顺序
在这里插入图片描述
在②中通过如下将组件引入:在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
现成代码见资源

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值