VUE
2、组件化开发
2.1、认识组件概念
- 对于学Java的人来说的话,这个词所要表达的意思再熟悉不过了,所谓组件就是:面向对象中的抽象、封装思想,而所谓的组件化就是:把功能用多组件的方式搭配起来编写( 有一个根组件,旗下有N多微型组件 ,粗暴理解就是:SpringCloud中的main()方法可以搭配很多不同功能的注解,main()方法就是根组件,不同功能的注解就是微型组件 ),那这些功能组成的应用程序就是一个组件化应用,因此:这样做之后,好处就是利于维护和提高代码的复用性了
- 但是对于前端的人来说,这个东西就需要特别解释一下:直接下定义就是 实现应用中局部功能代码和资源的集合
- 至于为什么要学组件化开发?
- 一是因为做的应用页面都是很复杂的,如果使用传统的CSS+HTML+JS,那么就会出现很多的js文件,不利于维护和 编写很费力的
- 二是因为组件化开发可以极好的复用代码、简化项目代码、所以也就提高了运行效率
- 同时组件又有单文件组件( 真实开发玩的 ) 和 非单文件组件
- 单文件组件:就是指只有一个组件组成( 即:是一个.vue的文件 )
- 非单文件组件:就是有N多个组件组成
2.2、非单文件组件
2.2.1、使用组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>玩一下组件</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app">
<!-- 3、使用组件 -->
<person></person>
<hr/>
<hobbys></hobbys>
</div>
<script>
// 去除浏览器控制台中的警告提示信息
Vue.config.productionTip = false;
// 玩组件三板斧
// 1、创建组件
const person = Vue.extend({
// 这里在基础篇中怎么玩就怎么玩,相应的也有watch、computed.....
// 但是:切记:不可以用el和data必须是函数式
/*
不可以用el的原因是:el指向的是具体的容器,这是根组件做的事情,现在这是是小弟
不可以用data对象式,而必须用函数式:是因为对象是一个引用地址嘛( 玩java的人很熟悉这个对象的事情 )
如果用引用一是Vue直接不编译、报错,二是就算可以用对象式,那几个变量都可以
指向同一个对象,那么就会产生:一个变量修改了对象中的东西,那么另一个变量指向
的是同一个对象,因此:数据也会发生改变
而函数式则不会,因为:函数式就会是哪个变量用的,里面的return返回值就是属于哪个变量
*/
// 使用模板,这个就需要直接写在组件里面了,如果:放到div容器的模板中,是会报错的
template: `
<div>
<h2>{{name}}</h2>
<h2>{{age}}</h2>
<h2>{{sex}}</h2>
</div>
`,
// 切记:这里是使用data的另一种写法 —— 函数式,必须用,前面基础篇说过了
data(){
return {
name: '紫邪情',
age: 18,
sex: '女'
}
}
})
// 再创建一个组件
const hobbys = Vue.extend({
template: `
<div>
<h2>{{one}}</h2>
<h2>{{two}}</h2>
<h2>{{three}}</h2>
</div>
`,
data(){
return {
one: '抠脚',
two: '玩',
three: '酒吧'
}
}
})
// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el:'#app',
// 这里面也可以使用这个编写data,和以前一样
data:{},
// 2、注册组件
components: {
// 前为 正式在页面中用的组件名( div模板中用的名字 ) 后为组件所在位置
// person: person, // 这种同名的就可以简写
// 简写
person,
hobbys
}
});
</script>
</body>
</html>
组件小结
-
Vue中使用组件的三板斧
- 1、创建组件
- 2、注册组件
- 3、使用组件( 写组件标签即可 )
-
如何定义一个组件? 使用Vue.extend( { options } )创建,其中options 和 new Vue( { options } )时传入的哪些option“几乎一样”,区别
- 1、el不要写 ——— 因为最终所有的组件都要经过一个vm的管理( 根组件 ),由vm中的el决定服务哪个容器
- 2、data必须写成函数式 ———— 因为可以避免组件被复用时,数据存在引用关系
- 另外:template选项可以配置组件结构
-
如何注册组件?
- 1、局部注册: 靠new Vue的时候传入components选项
- 2、全局注册:靠Vue。component( '组件名' , 组件 )
2.2.2、使用组件的注意点
- 1、创建组件时的简写问题
// 1、创建局部组件( 完整写法 )
const person = Vue.extend({
template: `
<div>
<h2>{{name}}</h2>
<h2>{{age}}</h2>
</div>
`,
data(){
return {
name: '紫邪情',
age: '女'
}
}
})
// 简写形式
const person2 = {
template: `
<div>
<h2>{{name}}</h2>
<h2>{{age}}</h2>
</div>
`,
data(){
return {
name: '紫邪情',
age: '女'
}
}
}
- 组件名的问题
- (1)、组件名为一个单词时
- 使用全小写字母 / 首字母大小都没问题
- (2)、组件名为多个单词组成时
- 全部用小写 / 使用 - 进行分割都没问题
- (3)、注意组件名别和HTML中的原生标签名一致,会冲突报错,HTML的限制就是上图中看源码中的哪些( 别想着它是小写,你搞大写,也是不行的^ _ ^ ),如果非要用HTML标签名,让人见名知意,那就在原生HTML标签名前加一些特定的词,如:user-input这种【 一般加的前缀都是功能点名称 】,记得千万别用:input、h2....此类名字来命名组件名
- (1)、组件名为一个单词时
- 3、关于组件在使用时的注意项
- (1)、可以使用双标签,如:,这种肯定没任何问题
- (2)、也可以使用自闭合标签,如:,但是这种有坑,这种使用方式需要脚手架支持,否则s数据渲染会出问题
使用组件注意点总结
- 1、对于组件名
- 一个单词组成时
- (1)、全小写,如:person
- (2)、首字母大写,如:Person
- 多个单词组成时
- (1)、全小写,如:myinfo
- (2)、使用 - 分割,如:my-info
- (3)、驼峰命名,如:MyInfo,但注意:目前没用脚手架之前最好别用,是因为指不定一会好使,一会不好使
- 一个单词组成时
注意事项:
-
(1)、组件名最好别和HTML的标签名一致,从而造成冲突( 非要用,可以采用加词 / 使用 - 分割 )
-
(2)、可以在创建组件时,在里面配置name选项,从而指定组件在Vue开发者工具中呈现的名字
-
2、关于组件标签( 使用组件 )
- (1)、使用双闭合标签也行,如:
- (2)、使用自闭合标签也行,如:
*注意事项:此种方式目前有坑,会出现后续组件不能渲染的问题,所以需要等到后续使用脚手架时才可以
- 3、创建组件的简写形式 const person = Vue.extend( { 配置选项 } ) 可以简写为 const person = { 配置选项 }
2.2.3、组件的嵌套 / 子父组件
- 很有用啊,真实开发玩的是单文件组件,逃不开这个点的,而且还会有子父组件通信和兄弟组件通信
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>组件嵌套</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app">
<!-- 3、使用组件 -->
<info></info>
</div>
<script>
// 去除浏览器控制台中的警告提示信息
Vue.config.productionTip = false;
// 1、定义组件
const person = {
template: `
<div>
<h2>{{name}}</h2>
<h2>{{sex}}</h2>
</div>
`,
data(){
return {
name: '紫邪情',
sex: '女'
}
}
}
const info = Vue.extend({
template: `
<div>
<h2>{{address}}</h2>
<h2>{{job}}</h2>
<!-- 这个组件中使用被嵌套的组件 -->
<person></person>
</div>
`,
data(){
return {
address: '浙江杭州',
job: 'java'
}
},
// 基础组件嵌套 —— 这个组件中嵌套person组件
/*
注意前提:被嵌套的组件 需要比 当前嵌套组件先定义( 如:person组件是在info组件前面定义的 )
原因:因为Vue解析模板时,会按照代码顺序解析,如果定义顺序反了
就会出现:这里用到的组件 在 解析时由于在后面还未解析从而出现找不到
*/
components: {
person,
}
})
// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el:'#app',
data:{},
// 2、注册组件 —— 由于info组件中 嵌套了 person组件,所以在这里只需要注册 info组件即可
components: {
info,
}
});
</script>
</body>
</html>
- 另一种嵌套:开发中玩的,我对那个div容器起的id值为app,是有用的
- 在开发中的嵌套是一个vm管理独一无二的app( 就是application 应用的意思 ),然后由app管理众多小弟
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vm管app,app管众多组件</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app"></div>
<script>
// 去除浏览器控制台中的警告提示信息
Vue.config.productionTip = false;
// 1、定义组件
const person = {
template: `
<div>
<h2>{{name}}</h2>
<h2>{{sex}}</h2>
</div>
`,
data(){
return {
name: '紫邪情',
sex: '女'
}
}
}
const info = Vue.extend({
template: `
<div>
<h2>{{address}}</h2>
<h2>{{job}}</h2>
<!-- 这个组件中使用被嵌套的组件 -->
<person></person>
</div>
`,
data(){
return {
address: '浙江杭州',
job: 'java'
}
},
components: {
person,
}
})
// 再定义一个app组件,用来管理其他组件
const app = {
// 这个app组件没有其他的东西,就是注册和使用被管理组件而已
components: {
// 有其他组件也可以注册在这里面,这里由于info管理了person,所以只注册info即可
info
},
template: `
<div>
<info></info>
</div>
`,
}
// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el:'#app',
data:{},
// 由于组件被app管理,所以:只注册app组件即可
components: { app },
// 使用组件
template: `
<div>
<app></app>
</div>
`,
});
</script>
</body>
</html>
2.2.4、认识VueComponent()函数
- 1、来看一下组件到底是谁?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>认识VueComponent</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app"></div>
<script>
// 去除浏览器控制台中的警告提示信息
Vue.config.productionTip = false;
// 1、定义组件
const person = Vue.extend({
template: `
<div>
<h2>{{name}}</h2>
<h2>{{job}}</h2>
<h2>{{address}}</h2>
</div>
`,
data(){
return {
name: '紫邪情',
job: 'java',
address: '浙江杭州'
}
}
})
const app = {
components: {person},
template: `
<div>
<person></person>
</div>
`,
}
// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el:'#app',
data:{},
components: {app},
template: `
<div>
<app></app>
</div>
`,
});
</script>
</body>
</html>
2.3、单文件组件
- 就是只有一个文件嘛,xxxx.vue
- 而xxxx就是前面说过的组件命名
- 单个单词:全小写、首字母大写
- 多个单词:用 - 进行分割、大驼峰命名
- 而开发中最常用的就是:首字母大写和大驼峰命名
2.3.1、疏通单文件组件的编写流程
- 前提:如果自己的编辑器是vscode,那么就给编辑器安装vetur插件,然后重启vscode,这个插件就是为了能够识别xxxx.vue文件的;如果自己是用的IDEA编辑器来写的vue,那么安装了vue.js插件之后,不用安装其他的插件都可以的
2.3.1.1、创建xxxx.vue文件
- 这个创建的就是单文件组件,前面玩非单文件组件,不是有三板斧吗,对照来看
- 创建了xxx.vue之后,是一个空文件,里面要写的东西就三样(模板template、交互script、样式style ),里面内容也对照非单文件组件来看
<template>
<div class="temp">
<!-- 这里面就是模板 以前在非单文件组件中用的template选项是怎么写的,这里面就是怎么写的-->
<h2>{{name}}</h2>
</div>
</template>
<script>
// 这里面就是交互( data、methods、watch、computed..... )
// 就是非单文件组件中的定义组件
/* const person = vue.extend({
// 这里就最好配置name选项了,一般都是当前创建的xxxx.vue中的xxxx名字即可
name: 'Person',
data() {
return {
name: '紫邪情'
}
},
// 这里面还可以写什么methods、watch.....之类的
})
*/
// 但是:上面是对照非单文件组件来写的,在这个单文件中其实换了一下下
// 1、这个组件是可以在其他地方复用的,所以:需要把这个组件暴露出去,然后再需要的地方引入即可
/*
这里需要使用到js中模块化的知识
export暴露 import引入嘛
但是:export暴露有三种方式
1、分别暴露 export const person = vue.extend({ 配置选项 }),
就是在前面加一个export而已
可是:根据前面非单文件的知识来看,这个是可以进行简写的
export person {}
2、统一暴露 就是单独弄一行代码,然后使用 export { 要进行暴露的名字 },多个使用 , 逗号隔开即可
3、默认暴露( vue中采用的一种,因为引入时简单 ) export default 组件名{ 配置选项 }
但是:组件名就是当前整个文件,所以可以省略
默认暴露引入: import 起个名字 from 它在哪里
而其他的暴露方式在引入时会有点麻烦
*/
// 正宗玩法
export default {
name: 'Person',
data() {
return {
name: '紫邪情'
}
},
// 再配置其他需要的东西也行 如:methods、watch、computed.....
}
</script>
<style>
/* 这里面就是template中的样式编写, 有就写,没有就不写 */
.temp{
color: purple;
}
</style>
2.3.1.2、注册组件到app中
- vm管app,app管其他的小弟,所以需要一个app组件,创建一个app.vue
<template>
<div>
<!-- 使用app管理的组件 -->
<person></person>
</div>
</template>
<script>
// 引入定义的person组件(要是有其他组件要引入那是一样的套路)
// 1Person.vue这个名字不正规啊,我只是为了排序才加了一个1
import person from "./1Person.vue"
export default {
name: 'App'
// 注册引起来的组件
components: {person} // 完成了引入和注册之后,在这里面就可以用引入的组件了
}
</script>
<style>
/* app是为了管理其他所有的组件,所以这个style其实不写也行( 按需要来吧 ) */
</style>
2.3.1.3、将app和vm绑定起来
- 新建一个main.js文件,创建这个文件的目的:一是让app和vm绑定,二是浏览器并不能识别.vue文件,所以根本展示不了,因此:需要将.vue文件转成js文件,这样浏览器就能解析了
// 1、引入app组件
import App from "./2App.vue"
// 2、把app组件和vm进行绑定
new Vue({
// 这里面和以前一样写法,当然:这里的el值绑定的是容器id,怕误会改成root也行
el: '#App',
components: {App}
})
2.3.1.4、创建容器
- 前面app组件和vm绑定了,但是vm中指定的el值,它绑定的容器还没有啊,因此:创建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>创建el容器</title>
<!--
记得要引入js,而此时就需要引入两个js,一个是main.js,一个是vue.js
可是:在解析下面的容器时,可能会导致js渲染不及时出问题
因此:引入js最好放在下面容器的后面引入
-->
</head>
<body>
<div id="App">
<!--
2、使用app组件,可以在这里使用,也可以不在这里使用
直接在app.vue中使用template选项进行使用
-->
<App></App>
</div>
<!--
1、引入js
vue.js是因为:main.js中new vue()需要它,所以:先引入vue.js
其次再引入main.js
-->
<script src="../../../js/vue.js"></script>
<script src="./3Main.js"></script>
</body>
</html>
- 而整个流程按照解析的逻辑来看就是如下流程
- 1、进入index.html,创建了div id = "App"容器,然后引入vue.js,再引入main.js
- 2、但是:引入main.js,去main.js里面开始解析时,发现:需要引入App.vue,所以:接着引入App.vue
- 3、进入App.vue,又发现需要引入Person.vue
- 4、将所有东西都引入完了之后,就可以依次进行渲染了( 逻辑就不说明了 ),而经过上面的逻辑梳理之后会发现:main.js就是入口,是从main.js开始引入,从而把其他的东西也给引入进来了
2.3.2、认识脚手架 vue cli
2.3.2.1、使用nodejs配置脚手架
-
前提:保证自己的电脑有nodejs,玩后端的人要是不了解nodejs的话,就把它理解为服务器,低配版的tomcat,
-
nodejs的配置很简单,官网进行下载、一直next、最后修改环境变量
- 有个注意点:选择安装目录时,别把nodejs安装到系统C盘了,不然很大可能出现权限不足,无法操作的问题,特别是:如果自己的电脑没升级,还是家庭版的而不是专业版的,这种问题更常见 出现这种问题就需要切换到管理员身份运行cmd才可以进行安装vue-cli了,甚至有时会奇葩点:需要在管理员身份下运行npm clean cache –force
- 然后再进入到C盘的用户目录下的appdata/roaming下把一个叫做nom-cache这个缓存文件删了,最后再用管理员身份运行npm clean cache –force清除缓存,搞完这些才可以安装vue cli脚手架
-
设置淘宝镜像地址
npm install -g cnpm --registry=https://registry.npm.taobao.org或者npm config set registry http://registry.npm.taobao.org
2.3.3、认识ref属性
2.3.4、props配置-获取外传数据
- 功能:让组件接收外部传进来的数据
- (1)、传递数据
- (2)、接收数据
- 1)、只接收 props: ['name']
- 2)、接收数据 + 数据类型限定
- (3)、接收数据 + 数据类型限定 + 必要性限制 + 数据默认值
- 注意:props中的数据是只读的,Vue底层会监测对props的修改,如果进行了修改,就会发出警告
-
如果业务需要修改,则:把props中的数据复制一份到data中,然后去修改data中的数据就可以了
-
须知:vue中优先使用props中的数据,然后再使用data中的数据( 可以使用data中的名字和props中的名字一样,然后去渲染,发现渲染出来的数据是props中的 )
-