十四天学会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数据,但是调用时有不同的实例 互相不会干扰

javascript 复制代码
 // 使用对象式和函数式的区别
        // 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()
javascript 复制代码
> > 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>

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

javascript 复制代码
 <!--准备好一个容器 -->
    <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>

几个注意点

javascript 复制代码
 <!--准备好一个容器 -->
    <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>

总结:

javascript 复制代码
几个注意点:
					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

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

javascript 复制代码
 <!--准备好一个容器 -->
    <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实例对象,也就是组件

下面案例中涉及到组件嵌套

总结

javascript 复制代码
关于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。
javascript 复制代码
  <!--准备好一个容器 -->
    <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>

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

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

一个重要的内置关系

javascript 复制代码
1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
				2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
javascript 复制代码
<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交互

书写顺序

在②中通过如下将组件引入:


现成代码见资源

相关推荐
yunvwugua__13 分钟前
Python训练营打卡 Day26
前端·javascript·python
满怀101521 分钟前
【Django全栈开发实战】从零构建企业级Web应用
前端·python·django·orm·web开发·前后端分离
Darling02zjh1 小时前
GUI图形化演示
前端
Channing Lewis1 小时前
如何判断一个网站后端是用什么语言写的
前端·数据库·python
互联网搬砖老肖1 小时前
Web 架构之状态码全解
前端·架构
showmethetime1 小时前
matlab提取脑电数据的五种频域特征指标数值
前端·人工智能·matlab
码农捻旧2 小时前
解决Mongoose “Cannot overwrite model once compiled“ 错误的完整指南
javascript·数据库·mongodb·node.js·express
淡笑沐白2 小时前
探索Turn.js:打造惊艳的3D翻页效果
javascript·html5·turn.js
海上彼尚2 小时前
秒删node_modules[无废话版]
vue.js·react.js
sunxunyong3 小时前
yarn任务筛选spark任务,判断内存/CPU使用超过限制任务
javascript·ajax·spark