浅谈Vue组件化编程思想及组件化的构建

目录

组件是什么?

组件化是什么?

为什么要提倡组件化编程?

非单文件组件

组件的创建步骤

命名注意点

组件的嵌套

 标准化开发(父类组件App)

对组件的加深理解(VueComponent构造函数)

VC原型链指向的更改(为什么VC会和VM基本相同)

单文件组件

创建-单文件组件

使用Vue脚手架(运行vue组件化应用)

安装脚手架 

运行上方定义的单文件组件 

 Vue脚手架目录结构解读

 render函数


组件是什么?

 定义 :组件(Component)是前端在单页面应用(SPA)上最好的一种实现方式,把所有功能模块拆解成单独的组件每个组件都有独立的作用域,且还可以相互通信。

通俗来说 组件我们可以看为是一个组成文件,它是由html,css,js以及资源文件(图片,音频等)所组成。页面上有许多功能模块,我们都可以将之定义为一个组件,每个组件的作用域是独立的。

组件化是什么?

当我们应用的功能都是使用组件的方式来构成实现,那么此应用就是一个组件化的应用。

为什么要提倡组件化编程?

 对比组件化,传统编写模式存在的弊端:

1.依赖关系混乱(文件引入),不好维护。

2.代码复用率相对不高。

 组件化优势:

1.将功能模块组件化,能提高代码复用性以及开发效率。

2.减小了beg调试区域,简化调试步骤。

3.有利于多人协作开发。

非单文件组件

组件的定义方式有两种,一种是非单文件组件定义,一种是单文件组件定义。

非单文件组件,顾名思义,就是一个文件中可以定义多个组件,使用.html文件后缀,而单文件组件一个文件仅包含一个组件,使用.vue文件后缀。

非单文件组件定义存在弊端:

1. 模板编写没有提示
2. 没有构建过程, 无法将 ES6 转换成 ES5
3. 不支持组件的 CSS
4. 真正开发中几乎不用

既然非单文件组件存在那么多弊端,为什么还要说明?

通过非单文件组件的学习,我们可以了解组件定义和使用流程以及一些细节,那么接下来的单文件组件就简单轻松多了。

组件的创建步骤

<body>
		<div id="root">
			<!-- //======第三步,组件的使用=======// -->
			<!-- 将定义好的组件名,使用如下方式插入在页面想要放置的位置 -->
			<hr>
            <!--使用标签方式1-->
			<show-info></show-info>
			<hr>
            <!--使用标签方式2(需要vue脚手架支持)-->
			<show-info/>
			<hr>
		</div>
		<script>
			//======第一步,组件的定义=======//
			//创建一个show-info组件
			 //Vue.extend()可不写,直接写配置项,但是底层还是会调用extend(),推荐先写
			const showinfo =  Vue.extend({
				//使用模板字符串定义组件的html结构
				template:`
					<div>
						<h2>姓名:{{name}}</h2>
						<h2>年龄:{{age}}</h2>
					</div>
				`,
				//组件中的data必须使用函数的形式书写,
				//因为我们需要保证组件复用的时候,每一个组件
				//都应该返回一份原始且独立的数据。
				data(){
					return{
						name:"Maohe",
						age:18
					}
				}
			})
			new Vue({
				el:"#root",
				data:{},
				//======第二步,组件的注册(局部注册)=======//
				components:{
					//第一个是定义组件名,第二个是组件定义对象(上方定义的)
					'show-info':showinfo
				}
			})
		</script>
	</body>

如上代码使用局部注册,组件仅在该vue实例中el定义的容器中奏效。

页面展示:

全局注册方式(在所有容器都可用)

//参数:第一个是定义组件名,第二个是组件定义对象
Vue.component('show-info',showinfo);

命名注意点

1.由一个单词组成(name)

        写法一:name(首字母小写)

        写法二:Name(首字母大写)

        不要在中间突然来个大写,例如naMe错误!会被认为成多个字母

2.由多个单词组成(myname)

        写法:my-name(烤肉串格式,由JS语法定义需要加""引号

        如果没有使用vue脚手架,不要使用myName格式,会报错!

组件的嵌套

顾名思义,就是组件下还可以定义组件。我们可以看一个图:

 写法: 

需求:我们定义一个school组件和,再在school组件下定义一个student组件。

页面vue开发工具和页面展示

 

 代码  

<body>
	<div id="root">
		
	</div>
	<script>
		//定义Student组件
		const Student = Vue.extend({
			name:"Student",
			template:`
				<div>
					<div>学生名称:{{studentName}}</div>
				</div>
			`,
			data(){
				return{
					studentName:"Maohe"
				}
			},
		})
		
		
		//定义School组件
		const School = Vue.extend({
			name:"School",
			template:`
				<div>
					<div>学校名称:{{schoolName}}</div>
					<hr>
					<Student></Student>
				</div>
			`,
			data(){
				return{
					schoolName:"OoO学校"
				}
			},
			//将Student组件定义在School下
			components:{Student}
			
		})
		new Vue({
			el:"#root",
			template:`
			<div>
				<School></School>
			</div>
			`,
			data:{},
			//注册School组件
			components:{School}
		})
	</script>
</body>

 标准化开发(父类组件App)

为了方便组件化开发的方便,我们需要定义一个顶级的组件,例如App组件,此App组件需要管理下属第一层的组件,vm则只需要管理App组件即可。图下如:

 就不进行代码演示了,就是利用组件的嵌套形式编写即可,将App组件注册在vm中,A、B和C组件注册在App组件中。

对组件的加深理解(VueComponent构造函数)

这里有几个关于组件的知识点,进行了解以后,对组件的内容会更加清晰。

我们先看一下如下代码(定义一个school组件)

const School = Vue.extend({
	name:"School",
	template:`
		<div>
			<div>学校名称:{{schoolName}}</div>
		</div>
	`,
	data(){
		return{
			schoolName:"OoO学校"
		}
	},
	
})

根据上述代码,解释组件内容:

1.School组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend()生成的,extend()方法的返回值就是VueComponent构造函数

2.我们只需要写<school/>或<school></school>,Vue解析时会帮我们自动创建school组件的实例对象,既内部执行了new VueComponent(option)

3.每次调用Vue.extend(),返回的都是一个全新的VueComponent。

4.VueComponent的实例对象,一般简称为VC

5.VM(Vue实例对象)和VC内部方法和属性基本相同,但是两者不可划等号。

   VC内部为什么会有VM的属性和方法如下会解释到。

VC原型链指向的更改(为什么VC会和VM基本相同)

解决问题:上方说了:VM(Vue实例对象)和VC内部函数和属性基本相同。

但是VC底层并没有对VM进行拷贝等类似的操作,那VC为什么会有于VM几乎相同的属性和函数呢?

重要等式Vuecomponent.prototype.__proto__ = Vue.prototype,通过此等式的分析,就会知道为什么VC内部会有和VM内部几乎相同的函数和属性。

 这里包含原型链的知识点,如果忘记了,在此带着回顾一下。

原型链作用:当我们创建了一个空对象person,打印:person.name,首先会在person对象中寻找属性name,发现person对象中没有此属性,接着就会沿着原型链寻找,直到找到尽头。如果没有就会报错。

原型链核心和过程简述

每个函数都会有prototype显示原型属性),此属性指向的是一个空的object对象,称为原型对象,每个实例对象上又会有__proto__隐式原型属性),__proto__指向的是实例对象构造函数的prototype最后也会指向原型对象,原型对象也是个对象(本质就是个空的Object对象),既然是对象就会有__proto__,原型对象上的__proto__指向的是Object的原型对象Object原型对象的__proto__为空,所以当找到此时,就是原型链的尽头

如果还是不太清除,可以访问我的主页,在专栏中找到JS,里面有原型链的说明,内存图解,可以更可视化的方式了解原型链的运行流程。

如上通过简述的方式回顾了原型链知识点,其实VC会拥有VM身上几乎所有的函数和属性,是因为vue在VC的原型链指向上做了一些指向改变才会有的。

正文解释

正常的调用extend()后,返回VC的构造函数, vc的构造函数指向的就是VC的原型对象,既然是对象,身上就会存在__proto__,本来直接指向的是Object的 原型对象,但是在此vue对指向进行了修改将原本指向Object原型对象的链重新指向Vue的原型对象身上(使得VC可以调用VM原型上的所有函数和属性),在通过Vue的原型对象才指到Object的原型对象,到达原型链尽头。

简易图解:

总结:就是因为Vue改变了VC的原型指向,使之指向了Vue的原型对象,所以VC就可以调用VM身上所定义的属性或函数了。所以Vm和VC才会几乎相同。

单文件组件

  概述

1.使用.vue后缀的文件编写。

2.文件命名建议使用大驼峰格式,组件名建议和文件名相同。

创建-单文件组件

首先我们需要创建.vue的文件,其次如果没有安装vue相关的插件,那么在.vue文件中将不会有代码高亮和一些必要的代码提示。

可以到自己的编码工具中下载对应插件,例如vscode中可以搜索"vetur"根据下载量下载版本。而HbuilderX中到工具-插件安装-点击到插件市场,搜索vue插件下载即可。

 单文件组件的基本结构

<template>
	<!-- HTML结构书写位置 -->
</template>

<script>
	// 数据和交互书写位置
</script>

<style>
	/* 样式书写位置 */
</style>

 需求:创建一个UserInfo组件(单文件组件方式)

<template>
	<!-- HTML结构书写位置 -->
	<div>
		<div id="name">用户姓名:{{userName}}</div>
		<div id="age">用户年龄:{{UserAge}}</div>
		<button @click="isAdult">是否成年?</button>
	</div>
</template>

<script>
	// 数据和交互书写位置(省略了Vue.extend(),直接写配置项)
	//也不需要变量来接收,直接将配置项模块暴露
	export default{
		name:"UserInfo",
		data(){
			return{
				userName:"Maohe",
				userAge:18
			}
		},
		methods:{
			isAdult(){
				this.userAge >= 18? alert("已经成年!") :alert("未成年!");
			}
		}
	}
</script>

<style>
	/* 样式书写位置 */
	#name{
		font-size: 19px;
	}
</style>

根据标准化开发,我们需要创建一个App组件(组件父类),用来管理所有组件,而让vm管理一个组件App即可。

 创建App组件 

<template>
    <div>
	    <UserInfo></UserInfo>
    </div>
</template>

<script>
	// 引入需要管理的子组件
	import UserInfo from './UserInfo.vue'
	
	// 将App组件暴露
	export default{
		name:"App",
        //注册子组件
        components:{
	        UserInfo
        }
	}
</script>

<style>
</style>

创建好app后,我们需要创建一个js文件(main.js=>入口文件),用来创建Vue实例,并且绑定容器和引入app组件

  创建main.js(入口文件) 

// 引入App组件
import App from './App.vue'

// 创建Vue实例,绑定容器
new Vue({
	el:"#root",
	// 给App组件进行注册
	components:{App}
})

以上都创建好了以后,我们就可以将js文件引入html文件中,至此一套标准的组件化开发就完成了。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="root">
			<App></App>
		</div>
		<script src="../../vue.js"></script>
		<script src="./main.js"></script>
	</body>
</html>

上方是我们手动开发了所有必要的代码,但是直接在浏览器中并不可以正常解析。因为浏览器不认识.vue文件,需要我们编译成js后浏览器才可以解析,这时我们就需要借助Vue脚手架(Vue-CLI 命令行界面),它是Vue提供的标准化开发工具,我们可以用来编译组件,使用脚手架还可以快速搭建项目结构,就可以省略掉许多地方的手写。

使用Vue脚手架(运行vue组件化应用)

安装脚手架 

 我们可以利用node环境的npm命令进行全局安装@vue/cli

//在命令行界面执行
npm install -g @vue/cli 

//要是npm下载速度慢,可以执行如下命令更换一个镜像
npm  config  set  registry https://registr y.npm.taobao.org

安装好脚手架后后,我们到想要创建vue项目的目录中打开cmd窗口,

例如:我们想要在2023-2-6目录下创建vue项目:

 或者直接打开cmd,使用cd,cd..等系统内置移动命令到达目录。

创建vue项目 

 创建好了以后,我们就可以在目录中看到了

运行上方定义的单文件组件 

众多目录和文件中我们现在只需要关心src目录和public目录。

将上方我们定义的单文件组件中的App组件,和Student组件给替换掉我们使用脚手架自动创建的项目对应文件,将自定义的App组件替换时,记得更改子组件路径,将我们自定义的Student组件放到components目录中

然后使用命令行进入(使用cd 目录名)创建好的vue项目

执行命令:npm run serve

 等待一会,会出现:

 如此我们就在8080端口上开启了一个服务,我们通过浏览器访问此路径就可以看到我们写的项目了。

 总结:其实已经可以发现,直接使用脚手架帮我们创建的项目,有着很全面的项目结构。

 至此,我们定义的单文件组件运行也成功了。

 Vue脚手架目录结构解读

 render函数

在入口文件main.js中,我们发现存在一个陌生的函数rander(),本来此文件是用来给App组件进行注册并且使用template来渲染App组件的,但是现在并没有给App组件注册也没有使用template来渲染App组件。仅仅只有一个rander函数,那么它的作用是什么呢?

 

 render函数的作用:渲染内容。

render函数的原貌

render(createElement){ //createElement名字自定义,原始文件中使用h
      return createElement("h1","你好")
}

render函数的参数就是一个函数,用来渲染内容。我们将组件作为函数放到参数函数里面就能渲染。在上方的书写中,我们可以将h1标签渲染并输入内容"你好"。或者我们可以将组件直接放到函数中当参数,就可以将组件进行渲染。

为什么需要使用rander函数渲染,而不是使用原来的方式先注册后放到template中进行解析渲染呢?

 其实就是因为我们在使用脚手架创建vue项目的时候,main.js上方引入的vue.js不是原生的是精简版的。此精简版的vue.js名字为vue.runtime.esm.js,这个精简版的与原生的vue.js的区别就是去掉了模板解析器

 验证 

 引入的是一个文件夹,我们查看文件夹。

 node.js模块化的特性,当我们引入一个文件夹时,会去访问此文件夹的packge.json配置文件。

 可以看到我们实际上默认是引入了module的值。

总结:所以就是因为我们引入的是精简版的vue(去掉了模板解析器),所以我们才不能使用template来解析,因为没有了模板解析器。之所以使用精简版的vue,是因为模板解析器占了vue的1/3空间。使用精简版更加的轻量级。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mao.O

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值