tips:
- 文章会从一些比较基础的用法写起,在于作为笔记;开发的时候有遗漏的知识点也可以查询;
- 可能会有一些比较深层的概念,可能会用链接的形式链接到其他文章,这些概念不理解也可能不影响开发。
目录
5.9.v-if、v-else、v-else-if指令(条件渲染)
1.Vue与渐进式的认识
Vue(读音/vju:/,类似于view)是一套用于构建用户界面的渐进式Javascript框架。
全称是Vue.js或者Vuejs,它是基于标准HTML、CSS和Javascript构建、提供了一套生命是的组件化的编程模型;
帮助你高效地开发用户界面。
1.1.渐进式的认识
在对于Vue.js中的解释中,涉及到一个概念:渐进式
Vue是一套渐进式Javascript框架,表示我们可以在项目中一点点来引入和使用Vue,而不一定需要全部使用Vue来开发整个项目。
在开发项目的时候可能会有很多功能,可以选择一部分使用Vue开发,其他的部分使用其他框架开发;可以一步一步地用Vue重构之前用其他框架开发的功能,用其他框架开发的功能也不会受到影响。
借用【一夜枫林】大佬对于渐进式框架的理解:你可以只用我的一部分,而不是用了我这一点就必须用我的所有部分。
1.2.Vue和其他流行框架
目前前端最流行的三大框架:Vue、React、Angular
- Vue在国内市场占有率最高,几乎所有的前端岗位都会对Vue有要求;
- React在国内外的市场占有率都是非常高的;也是前端工程师必须学习的一个框架。一般大型公司用得比较多;
- Angular入门门槛较高,需要学习typescript,并且国内市场占有率比较低;
三者都是非常优秀的框架,但是作为初学者的上手难度和目前职业发展方向而言,Vue和React是暂时较为适合学习的框架。
下面有框架的数据对比
![](https://i-blog.csdnimg.cn/blog_migrate/50a69f3d36ed5d402568fc5c09c7f227.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f457c0de500bedfcc0bb2ed75b968de2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0beb30df9dbfadfe3ea13097aa169c90.png)
![](https://i-blog.csdnimg.cn/blog_migrate/75b22a447361accd70be0b44fe129b5d.png)
1.3.Vue2和Vue3的选择
2020年9月19日,Vue3发布了正式版,它有着很多优点:
- 更好的性能
- 更小的体积
- 更好的TypeScript集成
- 更优秀的API设计
现在是学习Vue3的合适时期,Vue3目前是稳定的版本了,并且Vue3在2022年2月7日已经成为了默认安装版本;
很多公司目前新的项目都已经在使用Vue3来进行开发了,并且在面试的时候,几乎都会问到各种各样的Vue3相关问题。
而且作者尤雨溪也建议直接学Vue3,并且表示基础概念是一模一样的。
2.Vue的安装与引入使用
讲解完Vue的基本介绍,接下来要开始邂逅Vue了。
Vue是一个Javascript库,要把想象成封装好的库(类似于jQuery),在项目中引用并且使用它即可。
安装和使用Vue的方式:
- 在页面中通过CDN的方式引入;
- 下载Vue的JavaScript文件,并且自己手动引入;
- 通过npm包管理工具安装使用;
- 直接通过Vue CLI创建项目,并且使用它;
前期先采用前两种引入方式来学习Vue语法,后面两种等学了npm包管理工具和Vue CLI脚手架再使用。
作为初学者需要注意的点是:前面两种方式是写在html文件中的。如果使用的是vscode,!加上Tab键就可以快速搭建一个html结构。后面的代码都暂时写在body元素里面。
2.1.CDN引入
Vue的CDN引入
<script src="https://unpkg.com/vue@next"></script>
hello vue3的展示实现,vue相关的代码先不用关心,把注意放在CDN引入上面就好。
<div id="app"></div>
<script src="https://unpkg.com/vue@next"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
template: '<h2>hello vue3</h2>'
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
可以看到浏览器运行了Vue代码中template的内容。
2.2.下载Vue源码引入
打开https://unpkg.com/vue@nextVue源码的链接,复制其中所有的代码。
创建新的js文件,将代码复制到里面,可以命名为vue.js。
使用script标签,引入刚才的文件。
<div id="app"></div>
//引入vue.js文件
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
template: '<h2>hello vue3</h2>'
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
在前期的学习过程中建议使用Vue源码引入的方式,因为CDN引用可能会受到网络的影响,使用本地的Vue源码效率高一点。
3.声明式编程和MVVM模型概念理解
这两个概念可能不能实际应用在开发中,但是编程思想也是编程中很重要的部分,面试题中偶尔也会提及到这些概念。
3.1.声明式和命令式编程
如果有用过原生JavaScript开发过一些功能的话,可能很快就可以理解命令式编程和声明式编程的区别。借用【白纸一样】大佬的文章来基本了解命令式编程与声明式编程的区别。
原生开发和Vue开发的模式和特点,我们会发现是完全不同的,这里涉及到两种不同的编程范式:
- 声明式编程和命令式编程
- 命令式编程关注的是“how to do”,开发者完成整个过程;
- 声明式编程关注的是“what to do”,由框架(机器)完成“how”的过程;
在原生的实现过程中,我们是如何操作的呢?
- 我们每完成一个操作,都需要通过JavaScript编写一条代码,来给浏览器一个指令;
- 这样的编写代码的过程,我们称之为命令式编程;
- 在早期的原生JavaScript和jQuery开发的过程中,我们都是通过这种命令式的方式在编写代码的;
在Vue的实现过程中,我们是如何操作的呢?
- 我们会在createApp传入的对象中声明需要的内容,模板template、数据data、方法methods;
- 这样的编写代码的过程,我们称之为是声明式编程;
- 目前Vue、React、Angular、小程序的编程模式,我们称之为声明式编程;
Vue的编程模式是声明式编程。
3.2.MVVM模型
MVC和MVVM都是一种软件的体系结构
- MVC是Model – View –Controller的简称,是在前期被使用非常广泛的架构模式,比如iOS、前端;
- MVVM是Model-View-ViewModel的简称,是目前非常流行的架构模式; 通常情况下,我们也经常称Vue是一个MVVM的框架;
- Vue官方其实有说明,Vue虽然并没有完全遵守MVVM的模型,但是整个设计是受到它的启发的。
MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。
View层
视图层,通常是DOM层,给用户展示各种信息。
Model层
数据层,可能是自定义的数据,也有可能是从服务器,网络请求下来的数据。
ViewModel层
视图模型层,是view和model沟通的桥梁;
它实现了Data Binding,数据绑定,将model中的改变实时反应到view中;
它实现了DOM Listener,就是DOM监听,当DOM发生一些事件时,可以监听改变对应的data。
4.Vue基础 - Options API
已经学会引入Vue了,也讲解完了一些编程概念了,可以学习Vue基础了。
4.1.data属性(数据)
data属性使用频率很高,可以先来学习一下这个属性的使用。data里面主要来存放数据。
<div id="app">
<h2>{{message}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa"
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
data属性要传入一个函数,并且函数需要返回一个对象:
- 在Vue2.x的时候,也可以传入一个对象(官方推荐传入一个函数);
- 在Vue3.x的时候,必须传入一个函数,否则就会直接在浏览器中报错;
我们现在学习的是Vue3,所以要传入一个返回数据的对象的函数。
data: function(){
return {
message: "message"
}
}
4.2.methods属性(方法)
methods属性是一个对象,通常我们会在这个对象中定义很多的方法:
- 这些方法可以被绑定到模板中;
- 在该方法中,我们可以使用this关键字来直接访问到data放回的对象的属性;
<div id="app">
<h2>{{message}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa"
}
},
//可以编写方法
methods: {
messMethod() {
console.log(this.message)
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
在这个例子中就是定义了messMethod方法,并且使用到了data里面的message。
4.2.1.methods属性为什么不能使用箭头函数?
下面是官方文档给出的解释。
如果没有学习过this绑定的相关内容,可能会看不懂。有很多没有学习过的知识点,比如:箭头函数还有作用域(Ben Meng大佬写的)。不了解也可以,但记得methods一定不要用箭头函数。
//箭头函数类似于这种
var methods = () => {
console.log("里面可以写内容")
}
我们在methods中要使用data返回对象中的数据:
- 那么这个this是必须有值的,并且应该可以通过this获取到data返回对象中的数据。
那么我们这个this能不能是window呢?
- 不可以是window,因为window中我们无法获取到data返回对象中的数据;
- 但是如果我们使用箭头函数,那么这个this就会是window了;
为什么是window呢?
- 这里涉及到箭头函数使用this的查找规则,它会在自己的上层作用于中来查找this;
- 最终刚好找到的是script作用于中的this,所以就是window;
4.2.2.methods属性中的this指向什么?
这块内容也是比较难理解的,可以先理解this指向规则,事实上Vue的源码当中是对methods中的所有函数进行了遍历,并且通过bind绑定了this。
所以methods才能使用data中的数据。
4.3.computed属性(计算属性)
我们知道,在模板中可以直接通过插值语法显示一些data中的数据。
但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示;
- 比如我们需要对多个data数据进行运算、三元运算符来决定结果、数据进行某种转化后显示;
- 在模板中使用表达式,可以非常方便的实现,但是设计它们的初衷是用于简单的运算;
- 在模板中放入太多的逻辑会让模板过重和难以维护;
- 并且如果多个地方都使用到,那么会有大量重复的代码;
我们有没有什么方法可以将逻辑抽离出去呢?
- 可以,其中一种方式就是将逻辑抽取到一个methods中,放到methods的options中;
- 但是,这种做法有一个直观的弊端,就是所有的data使用过程都会变成了一个方法的调用;
- 另外一种方式就是使用计算属性computed;
Vue官方说:对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性。
4.3.1.computed的基本用法
如果我们要反转一个字符串,可以使用computed。
<div id="app">
<h2>{{string}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "first second"
}
},
computed: {
string() {
return this.message.split(" ").reverse().join(" ")
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
注意:
- 计算属性看起来像是一个函数,但是我们在使用的时候不需要加();
- 并且计算属性是有缓存的;
4.3.2.计算属性和methods的区别
<div id="app">
<!-- 使用计算属性 -->
<h2>{{string}}</h2>
<h2>{{string}}</h2>
<h2>{{string}}</h2>
<!-- 使用方法 -->
<h2>{{getString()}}</h2>
<h2>{{getString()}}</h2>
<h2>{{getString()}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "first second"
}
},
methods: {
getString() {
console.log('调用methods');
return this.message.split(" ").reverse().join(" ")
}
},
computed: {
string() {
console.log('调用computed');
return this.message.split(" ").reverse().join(" ")
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
看起来好像差不多啊,但是计算属性是有缓存的,而方法没有。
可以看到虽然都是展示了三次数据,computed只调用了一次,而methods调用了三次。
- 这是因为计算属性会基于它们的依赖关系进行缓存;
- 在数据不发生变化时,计算属性是不需要重新计算的;
- 但是如果依赖的数据发生变化,在使用时,计算属性依然会重新进行计算;
总结computed和methods的区别:
- 计算属性会缓存,但是方法不会,在多次使用一个数据的时候,计算属性性能更好。
- 计算属性放在插值语法里面后面不需要加小括号,方法需要。
4.4.watch属性(侦听器)
开发中我们在data返回的对象中定义了数据,这个数据通过差值语法等方式绑定到template中;
数据发生变化的时候,template会自动更新显示最新的数据;
我们如果希望在代码逻辑中监听某个数据的变化,就需要用侦听器watch来侦听了。
<div id="app">
<h2>{{message}}</h2>
<h2>{{info.name}} - {{info.age}}</h2>
<button @click="btnClick">按钮</button>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa",
info: {
name: "zzz",
age: 18
}
}
},
methods: {
btnClick() {
this.message = "bbbb",
this.info = {name: "www", age: 19}
}
},
// 监听message和info
watch: {
message(newValue, oldValue){
console.log(newValue, oldValue);
},
info(newValue, oldValue) {
console.log({...newValue});
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
将想要侦听的字符串或者数组、对象作为watch的函数名。
同时这个函数有两个参数:
- 第一个参数是变化后的值;
- 第二个参数是旧值。
4.4.1.watch的配置选项
<div id="app">
<h2>{{message}}</h2>
<h2>{{info.name}} - {{info.age}}</h2>
<button @click="btnClick">按钮</button>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa",
info: {
name: "zzz",
age: 18
}
}
},
methods: {
btnClick() {
this.message = "bbbb",
this.info.name = "cccc"
}
},
// 监听message
watch: {
message(newValue, oldValue){
console.log(newValue, oldValue);
},
info(newValue, oldValue) {
console.log({...newValue});
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
上面的例子: 当我们点击按钮的时候会修改info.name的值; 这个时候我们使用watch来侦听info,可以侦听到吗?答案是不可以。
这是因为默认情况下,watch只是在侦听info的引用变化,对于内部属性的变化是不会做出响应的:
- 这个时候我们可以使用一个选项deep进行更深层的侦听;
- 注意前面我们说过watch里面侦听的属性对应的也可以是一个Object;
还有另外一个属性,是希望一开始的就会立即执行一次:
- 这个时候我们使用immediate选项;
- 这个时候无论后面数据是否有变化,侦听的函数都会有限执行一次;
watch: {
message(newValue, oldValue){
console.log(newValue, oldValue);
},
info:{
handler(newValue, oldValue) {
console.log({...newValue}, {...oldValue});
},
deep: true,
immediate: true
}
}
4.4.2. watch的其他方式
还有一种侦听对象值的语法,写在watch里面。
"info.name": function(newValue, oldValue) {
console.log(newValue, oldValue);
}
还有另外一种方式就是使用 $watch 的API:
我们可以在created的生命周期(后续会讲到)中,使用 this.$watchs 来侦听;
第一个参数是要侦听的源;
第二个参数是侦听的回调函数callback;
第三个参数是额外的其他选项,比如deep、immediate;
4.5.VSCode快速生成代码片段
我们在练习Vue的过程中,有些代码片段是需要经常写的,我们在VSCode中我们可以生成一个代码片段,方便我们快速生成。
VSCode中的代码片段有固定的格式,所以我们一般会借助于一个在线工具来完成。
具体的步骤如下:
- 第一步,复制自己需要生成代码片段的代码;
<!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>Document</title>
</head>
<body>
<div id="app">
<h2>{{message}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa"
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
</body>
</html>
- 第二步,https://snippet-generator.app/在该网站中生成代码片段;
将右边生成的内容复制。
- 第三步,在VSCode中配置代码片段;
打开VSCode,菜单栏=>文件=>首选项=>用户片段(或者配置用户代码片段);
把复制的代码粘贴进去;
这样在html页面输入vueapp的时候就会生成对应的代码片段了。
5.Vue模板语法
Vue的开发模式大多数情况下,都是使用基于HTML的模板语法;
在模板中,允许开发者以声明式的方式将DOM和底层组件实例的数据绑定在一起;
在底层的实现中,Vue将模板编译成虚拟DOM渲染函数。
5.1.Mustache双大括号语法(插值语法)
如果我们希望把数据显示到模板中,使用最多的是Mustache双大括号语法插值;
当data中的数据发生改变时,对应的内容也会发生更新。
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa bbbb",
counter: 100,
age: 20
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
5.1.1.插值语法基本使用
插值语法的双大括号内可以加入空格,HTML元素里面也可以插入其他内容。
<div id="app">
<!-- 基本使用 -->
<h2>{{message}}</h2>
<!-- 插值语法里面可以加空格 -->
<h2>也可以插入其他内容 {{ counter }}</h2>
</div>
5.1.2.插值语法之JavaScript表达式
插值语法中不仅仅可以是data中的属性,也可以是一个JavaScript的表达式,还可以调用methods中的函数。
<!-- 表达式 -->
<h2>{{ counter * 2 }}</h2>
<h2>{{ message.split(" ") }}</h2>
<h2>{{ age>18 ? "成年" : "未成年" }}</h2>
5.2.v-once指令(了解)
这个指令用得比较少,主要是用于指定元素或者组件只渲染一次。
当数据发生变化时,元素或者组件以及其所有的子元素将视为静态内容并且跳过;
该指令可以用于性能优化;
<div id="app">
<h2 v-once >count: {{count}}</h2>
<button @click="add">+</button>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
count: 0
}
},
methods: {
add(){
this.count++
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
如果没有加v-once指令,在点击了按钮之后,就会触发methods中的add方法,count自增。但是这个元素只渲染一次,所以count无论按钮按多少次,都会是0。
5.3.v-text指令(了解)
v-text这个指令也用得比较少,有点类似于双大括号语法,但是没有双大括号语法那么灵活。
<div id="app">
<h2>前面可以写{{ message }}后面也可以</h2>
<h2 v-text="message"></h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa"
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
5.4.v-html指令(了解)
默认情况下,如果我们展示的内容本身是 html 的,那么vue并不会对其进行特殊的解析。
如果我们希望这个内容被Vue可以解析出来,那么可以使用 v-html 来展示;
<div id="app">
<h2>{{content}}</h2>
<h2 v-html="content"></h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
content: `<span style="color: red; font-size: 30px">哈哈哈</span>`
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
使用了v-html的就可以解析出来了,没有用v-html的是直接将html标签输出出来。
在这个案例中有用到模板字符串(` `),可以了解一下它的使用场景。
5.5.v-pre指令(了解)
在html标签里面有时候想用{{}},但是默认情况下会解析成双大括号语法,就可以在标签里面添加v-pre。
<div id="app">
<h2>{{message}}</h2>
<h2 v-pre>{{message}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa"
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
5.6.v-cloak(了解)
cloak是斗篷的意思,这个指令保持在元素上知道关联组件实例结束编译。
如果给Vue的编译加上定时器用来模拟网络不好的时候编译缓慢的情况。
<div id="app">
<h2>{{message}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
setTimeout(() => {
const app = Vue.createApp({
data: function(){
return {
message: "aaaa"
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
}, 2000);
2秒之前发现会出现这样的显示在页面上,对于用户来说是不友好的,所以使用v-cloak和CSS规则来解决这个问题。
<style>
[v-cloak] {
display: none;
}
</style>
<div id="app">
<h2 v-cloak>{{message}}</h2>
</div>
在可能会加载的元素放上v-cloak,给它设置样式。
5.7.v-bind指令(绑定属性)
从这里开始便是经常使用的指令了,一定要好好理解。
前面的一系列指令,主要是将值插入到模板内容中。但是除了内容需要动态来决定之外,某些属性我们也希望动态绑定。我们使用v-bind来绑定属性。
- 比如动态绑定a元素的href属性;
- 比如动态绑定img元素的src属性。
v-bind语法糖(简写)形式: :
5.7.1.绑定基本属性
v-bind用于绑定一个或多个属性值。
<div id="app">
<a v-bind:href="href">搜索一下</a>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
href: "https://www.baidu.com"
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
a元素里面的href属性加上v-bind指令,可以动态地改变href里面的网址,将href的网址放在data里面。
5.7.2.v-bind的语法糖(简写)
在开发中我们经常会使用语法糖(来自Franco蜡笔小强)的形式来编写,语法糖会更加简洁。
<a v-bind:href="href">搜索一下</a>
<a :href="href">搜索一下</a>
5.7.3.绑定class
在开发时,有时候我们可以动态改变元素class来改变样式。
<style>
.active {
color: red;
}
</style>
<body>
<div id="app">
<button :class="isActive ? 'active' : ''" @click="activeClick">按钮</button>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
isActive: false
}
},
methods: {
activeClick() {
this.isActive = !this.isActive
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
</body>
在本例子中,在点击了按钮之后触发了activeClick事件,将isActive置为true状态。而class又是用v-bind动态绑定的,三元表达式isActive为true,class为acitve,所以文字的颜色变成了红色。
5.7.4.绑定class-对象语法
我们可以传递一个对象来动态切换class。
<div class="aaa" :class="{nba: isActive, 'cba': true}">2222</div>
可以传入多个键值对{class类: boolean值}。
在上面的例子中
- 没有带v-bind的aaa类不管状态都可以加入这个div元素中,
- 而带了v-bind的类可以根据后面的boolean值来判断要不要把类名加入到这个div元素中。
- 其中isActive可以是data属性里面的boolean类值。
5.7.5.绑定class-数组语法
我们可以把数组传给:class,以应用一个class列表;
<!-- 直接传入一个数组 -->
<h2 :class="['abc', className]">数组语法</h2>
<!-- 数组中也可以使用三元运算符或者绑定变量 -->
<h2 :class="['abc', className, isActive? 'acitve' : '']">数组语法</h2>
<!-- 数组中使用对象语法 -->
<h2 :class="['abc', className, {'active': isActive}]">数组语法</h2>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
isActive: true
className: "cba"
}
},
如果在数组中不是以字符串的形式存放的,比如例子中的className,就会使用data中的className。
5.7.6.绑定style
我们可以利用v-bind:style来绑定一些CSS内联样式:
- 某些样式我们需要根据数据动态来决定;
- 比如某段文字的颜色和大小。
绑定style中的CSS property(属性名)可以用驼峰式或短横线分隔(需要用引号包裹)来命名。
<h2 :style="{fontSize: '40px' , 'background-Color': 'blue'}">{{message}}</h2>
- 如果使用驼峰式就不需要用引号,使用短横线分隔就需要用引号;
- 多个属性之间要使用逗号分隔。
5.7.7.绑定style-对象语法
- 我们可以传入一个确定内容的对象;
- css属性值也可以来自data;
- 甚至直接在data中定义好一个对象。
<div id="app">
<!-- 传入一个对象,并且对象内容都是确定的 -->
<div :style="{color: 'red' , fontSize: '40px' , 'background-Color': 'blue'}">{{message}}</div>
<!-- css属性值可以来自data,fontSize中的size来自data -->
<div :style="{color: 'red' , fontSize: size +'px' , 'background-Color': 'blue'}">{{message}}</div>
<!-- 直接在data定义好一个对象 -->
<div :style="styleObj">{{message}}</div>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa",
size: 20,
styleObj:{color: 'green', fontSize: '80px', backgroundColor: 'pink'}
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
5.7.8.绑定style-数组语法
数组里面可以包含多个对象,在data中定义多个style对象,将多个样式对象应用在一个元素上。
<!-- 直接在data定义好两个对象 -->
<div :style="[styleObj1, styleObj2]">{{message}}</div>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
styleObj1:{color: 'green', backgroundColor: 'pink'},
styleObj2:{fontSize: '80px'}
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
5.7.9.绑定元素的属性-对象
如果我们希望将一个对象的所有属性,绑定到元素上的所有属性,应该怎么做呢?
我们可以直接使用 v-bind 绑定一个 对象;
<div v-bind="infos">{{message}}</div>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
infos: {name: 'zzz', age: 20, height: 1.11}
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
5.8.v-on指令(绑定事件)
v-on的使用:
缩写:@
预期:Function | Inline Statement | Object
参数:event
修饰符:
- .stop - 调用 event.stopPropagation()。
- .prevent - 调用 event.preventDefault()。
- .capture - 添加事件侦听器时使用 capture 模式。
- .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
- .{keyAlias} - 仅当事件是从特定键触发时才触发回调。
- .once - 只触发一次回调。
- .left - 只当点击鼠标左键时触发。
- .right - 只当点击鼠标右键时触发。
- .middle - 只当点击鼠标中键时触发。
- .passive - { passive: true } 模式添加侦听器
用法:绑定事件监听
5.8.1. 绑定基本事件
绑定事件中,可以绑定一个表达式,也可以绑定一个方法。
在实际开发中,绑定方法是更加常用的。
<div id="app">
<div>{{counter1}}</div>
<!-- 绑定表达式 -->
<button v-on:click="counter1++">+</button>
<div>{{counter2}}</div>
<!-- 绑定方法 -->
<button v-on:click="btnClick">+</button>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
counter1: 0,
counter2: 0
}
},
methods: {
btnClick() {
this.counter2 ++
}
},
});
//将app挂载到id为app的div上
app.mount("#app");
click鼠标点击事件是使用最频繁的一种事件,下面是一些可能会用到的事件。
焦点事件
事件名称 | 何时触发 |
---|---|
focus | 元素获得焦点(不会冒泡) |
blur | 元素失去焦点(不会冒泡) |
表单事件
事件名称 | 何时触发 |
---|---|
reset | 点击重置按钮时 |
submit | 点击提交按钮 |
键盘事件
事件名称 | 何时触发 |
---|---|
keydown | 按下任意按键 |
keypress | 除 Shift、Fn、CapsLock 外的任意键被按住(连续触发) |
keyup | 释放任意按键 |
鼠标事件
事件名称 | 何时触发 |
---|---|
click | 在元素上按下并释放任意鼠标按键。 |
contextmenu | 右键点击(在右键菜单显示前触发)。 |
dblclick | 在元素上双击鼠标按钮。 |
mousedown | 在元素上按下任意鼠标按钮。 |
mouseenter | 指针移到有事件监听的元素内。 |
mouseleave | 指针移出元素范围外(不冒泡)。 |
mousemove | 指针在元素内移动时持续触发。 |
mouseover | 指针移到有事件监听的元素或者它的子元素内。 |
mouseout | 指针移出元素,或者移到它的子元素上。 |
mouseup | 在元素上释放任意鼠标按键。 |
5.8.2.v-on的语法糖(简写)
v-on:click可以写成@click,是它的语法糖写法:
<button @click="btnClick">+</button>
5.8.3.v-on绑定多个事件
如果我们希望一个元素绑定多个事件,我们可以传入一个对象。但是这个时候就不要用简写形式@了。
<button v-on="{click: btnClick, mousemove: mouseMove}">+</button>
5.8.4.v-on的参数传递
当通过methods中定义方法,以供@click调用时,需要注意参数问题:
- 情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。 但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去;
<button @click="btnClick1">按钮</button>
btnClick1(e) {
console.log(e);
},
- 情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。
<button @click="btnClick2($event, 'other')">按钮</button>
btnClick2(event, message) {
console.log(event, message);
}
5.8.5.v-on的修饰符
v-on支持修饰符,修饰符相当于对事件进行了一些特殊的处理:
- .stop - 调用 event.stopPropagation()。取消冒泡事件
- .prevent - 调用 event.preventDefault()。取消默认事件
- .capture - 添加事件侦听器时使用 capture 模式。
- .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
- .{keyAlias} - 仅当事件是从特定键触发时才触发回调。
- .once - 只触发一次回调。
- .left - 只当点击鼠标左键时触发。
- .right - 只当点击鼠标右键时触发。
- .middle - 只当点击鼠标中键时触发。
- .passive - { passive: true } 模式添加侦听器
<button @click.stop="btnClick">按钮</button>
5.9.v-if、v-else、v-else-if指令(条件渲染)
v-if、v-else、v-else-if用于根据条件来渲染某一块的内容:
这些内容只有在条件为true时,才会被渲染出来;
这三个指令与JavaScript的条件语句if、else、else if类似;
<h2 v-if="score > 90">优秀</h2>
<h2 v-else-if="score > 80">良好</h2>
<h2 v-else-if="score > 60">及格</h2>
<h2 v-else>不及格</h2>
- v-if是惰性的;
- 当条件为false时,其判断的内容完全不会被渲染或者会被销毁掉;
- 当条件为true时,才会真正渲染条件块中的内容;
- 所以v-if会判断条件之后才会去渲染内容。
5.10. template元素
因为v-if是一个指令,所以必须将其添加到一个元素上:
但是如果我们希望切换的是多个元素呢?
此时我们渲染div,但是我们并不希望div这种元素被渲染; 这个时候,我们可以选择使用template;
template元素可以当做不可见的包裹元素,并且在v-if或者其他条件渲染指令上使用,但是最终template不会被渲染出来。
<div id="app">
<template v-if="show">
<h2>v-if</h2>
<h2>v-if</h2>
<h2>v-if</h2>
</template>
<template v-else>
<h2>v-else</h2>
<h2>v-else</h2>
<h2>v-else</h2>
</template>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
show: true
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
判断完条件之后,template不会渲染到DOM上面。
5.11.v-show指令(显示元素)
v-show和v-if的用法看起来是一致的,也是根据一个条件决定是否显示元素或者组件:
<div id="app">
<h2 v-show="isShow">v-show</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
isShow: true
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
5.11.1.v-show和v-if的区别
首先,在用法上的区别:
- v-show是不支持template;
- v-show不可以和v-else一起使用;
其次,本质的区别:
- v-show元素无论是否需要显示到浏览器上,它的DOM实际都是有存在的,只是通过CSS的display属性来进行切换;
- v-if当条件为false时,其对应的原生压根不会被渲染到DOM中;
<div id="app">
<h2 v-if="ifShow">v-if</h2>
<h2 v-show="isShow">v-show</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
ifShow: false,
isShow: false
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
在这个案例中,ifShow和isShow都是false,两个元素都不会显示,但是DOM树有一些区别。
用v-show渲染的h2中的style="display: none"印证了上面的用display属性来切换元素的显示与隐藏。
开发中如何进行选择呢?
- 如果我们的原生需要在显示和隐藏之间频繁的切换,那么使用v-show;
- 如果不会频繁的发生切换,那么使用v-if;
5.12.v-for指令(列表渲染)
在真实开发中,我们往往会从服务器拿到一组数据,并且需要对其进行渲染。
这个时候我们可以使用v-for来完成;
v-for类似于JavaScript的for循环,可以用于遍历一组数据;
就像是这样的一个页面,如果每个专辑都写一遍数据,就太麻烦了。所以我们可以把数据都放在一个数组或者对象里面,在需要开发这样的页面的时候使用v-for列表渲染就可以了。
5.12.1.v-for的数组用法
v-for的基本格式是 item in 数组:
数组通常是来自data和prop ,item是我们给每项元素起的一个别名,这个别名也可以自己定义。
使用item in array取数组的元素
<div id="app">
<h2 v-for="item in array">{{item}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
array: ["first", "second", "third", "fourth"]
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
在上面的案例中,使用了v-for遍历了array数组,array数组定义在data中。
有时候遍历数组时需要拿到数组的索引:
如果我们需要索引,可以使用格式 (item, index) in 数组:
数组元素项item在前面,索引项index在后面。
使用(item, index) in array取数组的元素和对象
<div id="app">
<h2 v-for="(item, index) in array" >{{index}} - {{item}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
array: ["first", "second", "third", "fourth"]
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
可以使用大括号语法把index和item输出出来。
5.12.2.v-for的对象用法
v-for在遍历对象的时候可以有三个参数,分别为value值、key键、index索引。
使用value in object取对象的值
<div id="app">
<h2 v-for="value in obj">{{value}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
obj: {
key1 : 'value1',
key2 : 'value2',
key3 : 'value3',
key4 : 'value4'
}
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
在一个值的时候,默认为value值。
使用(value, key) in object取对象的值和键
<div id="app">
<h2 v-for="(value, key) in obj">{{key}}-{{value}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
obj: {
key1 : 'value1',
key2 : 'value2',
key3 : 'value3',
key4 : 'value4'
}
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
要注意顺序,一般来说越重要的放得越前,对于对象来说value值是最重要的,key次之。
使用(value, key, index) in object取对象的值、键和索引
<div id="app">
<h2 v-for="(value, key, index) in obj">{{index}}-{{key}}-{{value}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
obj: {
key1 : 'value1',
key2 : 'value2',
key3 : 'value3',
key4 : 'value4'
}
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
我们比较少取对象的索引值,所以把index索引这个参数放在最后。
数组和对象的遍历开发的时候用得还是比较多的,自己实践一遍印象会更深。
5.12.3.v-for的其他用法
v-for同时也支持数字的遍历: 每一个item都是一个数字;
v-for也可以遍历其他可迭代对象(Iterable)。
这些用法用得比较少,演示一个数字的遍历。
<span v-for="item in 10">{{item}}</span>
5.12.4.template元素
类似于v-if,你可以使用 template元素 来循环渲染一段包含多个元素的内容:
我们使用template来对多个元素进行包裹,而不是使用div来完成;
<div id="app">
<template v-for="(value, key) in info">
<li>{{key}}</li>
<li>{{value}}</li>
<br/>
</template>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
info: {
key1: 'value1',
key2: 'value2'
}
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
在编译完成之后,template就会消失,不会渲染到DOM树上。
5.12.5.v-for数组更新检测
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。
这些被包裹过的方法包括: push() pop() shift() unshift() splice() sort() reverse() 。如果没有了解过这些数组方法,可以先看一下。
我们编写一个案例查看在数组变化的时候,对应的视图会不会更新。
<div id="app">
<h2 v-for="item in array">{{item}}</h2>
<button @click="addClick">添加</button>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
array:["a","b","c"]
}
},
methods: {
addClick() {
this.array.push('d')
}
},
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
我们在点击按钮的时候,把d放到数组后面,v-for渲染的数组会变化。
说明使用push() pop() shift() unshift() splice() sort() reverse()这些方法让数组发生变化的时候,视图会发生改变。
上面的方法会直接修改原来的数组;
但是某些方法不会替换原来的数组,而是会生成新的数组,比如 filter()、concat() 和 slice()。
5.12.6.v-for中的key的作用
在使用v-for进行列表渲染时,我们通常会给元素或者组件绑定一个key属性。
这个key属性的作用(_Dax1大佬写的)呢?我们先来看一下官方的解释:
- key属性主要用在Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes;
- 如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法;
- 而使用key时,它会基于key的变化重新排列元素顺序,并且会移除/销毁key不存在的元素;
官方给出的解释太抽象了,可以看上面链接的解释。
简单来说,key可以通过diff算法让元素在添加元素、删除元素、重新排列元素的时候效率更高。有些场景不加key会报错。
5.13. v-model指令(双向绑定)
表单提交时开发中非常常见的功能,也是和用户交互的重要手段:
- 比如用户在登录、注册时需要提交账号密码;
- 比如用户在检索、创建、更新信息时,需要提交一些数据;
这些都要求我们可以在代码逻辑中获取到用户提交的数据,我们通常会使用v-model指令来完成:
- v-model指令可以在表单 input、textarea以及select元素上创建双向数据绑定;
- 它会根据控件类型自动选取正确的方法来更新元素;
- 尽管有些神奇,但 v-model 本质上不过是语法糖,它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理;
<input type="text" v-model="message">
<h2>{{message}}</h2>
在输入到输入框的时候,下面的文字也会跟着变化。
5.13.1.v-model的原理
官方有提到,v-model的原理其实是有两个操作:
- v-bind绑定value属性的值;
- v-on绑定input事件监听到函数中,函数会获取最新的值赋值到绑定的属性中;
我们可以使用v-bind和v-on来实现v-model的效果。
v-model算是v-bind和v-on实现双向绑定的一个语法糖。
<div id="app">
<input type="text" :value="message" @input="inputChange">
<h2>{{message}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa"
}
},
methods: {
inputChange(event) {
this.message = event.target.value
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
5.13.2.v-model绑定textarea
v-model也可以绑定textarea多行文本框。和input的绑定方法类似。
<textarea v-model="message" cols="30" rows="10"></textarea>
<h2>{{message}}</h2>
5.13.3.v-model绑定checkbox
单个勾选框:
- v-model即为布尔值。
- 此时input的value属性并不影响v-model的值。
<div id="app">
<label for="cb">
<input type="checkbox" id="cb" v-model="isAgree">同意协议
</label>
<h2>{{isAgree}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
isAgree: false
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
多个复选框:
- 当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。
- 当选中某一个时,就会将input的value添加到数组中。
<div id="app">
<label for="basketball">
<input type="checkbox" id="basketball" value="basketball" v-model="isAgree">篮球
</label>
<label for="football">
<input type="checkbox" id="football" value="football" v-model="isAgree">足球
</label>
<label for="badminton">
<input type="checkbox" id="badminton" value="badminton" v-model="isAgree">羽毛球
</label>
<h2>{{isAgree}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
isAgree: []
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
5.13.4.v-model绑定radio
radio只能选一个,单选框。
<div id="app">
<label for="male">
<input type="radio" id="male" value="male" v-model="gender">男
</label>
<label for="female">
<input type="radio" id="female" value="female" v-model="gender">女
</label>
<h2>{{gender}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
gender: ""
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
5.13.5.v-model绑定select
select和checkbox类似,也分成单选和多选两种情况。
单选:
- 只能选中一个值 v-model绑定的是一个值;
- 当我们选中option中的一个时,会将它对应的value赋值;
<div id="app">
<select v-model="choose">
<option value="choose1">choose1</option>
<option value="choose2">choose2</option>
<option value="choose3">choose3</option>
</select>
<h2>{{choose}}</h2>
</div>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
choose: ""
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
</script>
多选:
- 可以选中多个值 v-model绑定的是一个数组;
- 当选中多个值时,就会将选中的option对应的value添加到数组中;
在select元素多加multiple 和size就可以实现多选。
<select v-model="choose" multiple size="3">
<option value="choose1">choose1</option>
<option value="choose2">choose2</option>
<option value="choose3">choose3</option>
</select>
<h2>{{choose}}</h2>
按住ctrl就可以多选。
5.13.6.v-model修饰符 - lazy
前面写的input案例中,只要在输入框输入内容,绑定的属性值就会更新。有时候我们不需要那么快响应,以达到优化性能的作用。
lazy有懒惰的意思,如果在v-model后面加上lazy修饰符,在失去焦点的时候才会更新。
<input type="text" v-model.lazy="message">
<h2>{{message}}</h2>
5.13.7.v-model修饰符 - number
如果我们希望在input框里面输入的内容是number类型,就可以使用.number修饰符。
<input type="text" v-model.number="number">
<h2>{{typeof(number)}}</h2>
在vue3之后,input元素的type改成number,v-model就会自动根据type转化类型。
<input type="number" v-model="number">
<h2>{{typeof(number)}}</h2>
5.13.8.v-model修饰符 - trim
如果要自动过滤用户输入的空白字符,可以使用.trim修饰符。
<input type="text" v-model.trim="number">
<h2>{{number}}</h2>
过滤是过滤前后的空白字符,字符中间的空白不会过滤。
6.Vue组件化 - 组件化开发基础
组件化是Vue、React、Angular的核心思想,也是我们学习的重点:
- 前面我们的createApp函数传入了一个对象App,这个对象其实本质上就是一个组件,也是我们应用程序的根组件;
- 组件化提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用;
- 任何的应用都会被抽象成一颗组件树;
6.1.认识组件化开发
在开发中如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展;
但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了;
如果我们将一个个功能块拆分后,就可以像搭建积木一下来搭建我们的项目;
我们需要通过组件化的思想来思考整个应用程序:
- 我们将一个完整的页面分成很多个组件;
- 每个组件都用于实现页面的一个功能块;
- 而每一个组件又可以进行细分;
- 而组件本身又可以在多个地方进行复用。
后面学习一下Vue怎么注册组件,如何使用这个注册后的组件。
6.2. 注册全局组件
全局组件需要使用我们全局创建的app来注册组件;
- 先编写一个template模板,加上id;
- 通过component方法传入组件名称、组件对象(对象里面需要编写template与对应的id)即可注册一个全局组件了;
- 之后,我们可以在App组件的template中直接使用这个全局组件。
<div id="app">、
//步骤三
<cpn-name></cpn-name>
<cpn-name></cpn-name>
<cpn-name></cpn-name>
</div>
//步骤一
<template id="cpn">
<h2>template</h2>
</template>
<script src="./vue.js"></script>
<script>
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa"
}
}
});
//将app挂载到id为app的div上
//步骤二
app.component("cpn-name", {
template: "#cpn"
})
app.mount("#app");
</script>
组件本身也有自己的代码逻辑
比如组件自己的data、computed、methods。
app.component("cpn-name", {
template: "#cpn",
data() {
return {
message: "components data"
}
},
methods: {
componentMethods() {
console.log("components methods");
}
}
})
6.3.组件的命名
使用app.component注册一个组件的时候,第一个参数是组件的名称,定义组件名有两种方式:
方式一:使用kebab-case(短横线分割符)
- 当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>;
app.component("my-component-name",{
template: "#cpn"
})
方式二:使用PascalCase(驼峰标识符)
- 当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。
- 也就是说 <my-component-name> 和 <MyComponentName> 都是可接受的;
app.component("MyComponentName",{
template: "#cpn"
})
6.4. 注册局部组件
全局组件往往是在应用程序一开始就会全局组件完成,那么就意味着如果某些组件我们并没有用到,也会一起被注册,打包的JavaScript包会更大:
- 比如我们注册了三个全局组件:ComponentA、ComponentB、ComponentC;
- 在开发中我们只使用了ComponentA、ComponentB,如果ComponentC没有用到但是我们依然在全局进行了注册,那么就意味着类似于webpack这种打包工具在打包我们的项目时,我们依然会对其进行打包;
- 这样最终打包出的JavaScript包就会有关于ComponentC的内容,用户在下载对应的JavaScript时也会增加包的大小;
所以在开发中我们通常使用组件的时候采用的都是局部注册:
- 局部注册是在我们需要使用到的组件中,通过components属性选项来进行注册;
- 比如之前的App组件中,我们有data、computed、methods等选项了,事实上还可以有一个components选项;
- 该components选项对应的是一个对象,对象中的键值对是 组件的名称: 组件对象;
//vue相关的代码
const app = Vue.createApp({
data: function(){
return {
message: "aaaa"
}
},
// component属性
component: {
// 组件名称: 组件对象
"MyComponent": {
template: "#cpn",
data() {
return {
message: "cpn1"
}
}
},
"MySecondComponent": {
template: "#cpn2",
data() {
return {
message: "cpn2"
}
}
}
}
});
//将app挂载到id为app的div上
app.mount("#app");
当然component对象中的组件对象也可以抽离出来,使用变量。
6.5.Vue的开发模式
目前我们使用vue的过程都是在html文件中,通过template编写自己的模板、脚本逻辑、样式等。
但是随着项目越来越复杂,我们会采用组件化的方式来进行开发:
- 这就意味着每个组件都会有自己的模板、脚本逻辑、样式等;
- 当然我们依然可以把它们抽离到单独的js、css文件中,但是它们还是会分离开来;
- 也包括我们的script是在一个全局的作用域下,很容易出现命名冲突的问题;
- 并且我们的代码为了适配一些浏览器,必须使用ES5的语法;
- 在我们编写代码完成之后,依然需要通过工具对代码进行构建;
所以在真实开发中,我们可以通过一个后缀名为 .vue 的single-file components (单文件组件) 来解决,并且可以使用webpack或者vite或者rollup等构建工具来对其进行处理。
6.5.1.单文件组件的特点
在这个组件中我们可以获得非常多的特性:
- 代码的高亮;
- ES6、CommonJS的模块化能力;
- 组件作用域的CSS;
- 可以使用预处理器来构建更加丰富的组件,比如TypeScript、Babel、Less、Sass等;
6.5.2. 使用单文件组件(SFC)的方法
如果我们想要使用这一的SFC的.vue文件,比较常见的是两种方式:
- 方式一:使用Vue CLI来创建项目,项目会默认帮助我们配置好所有的配置选项,可以在其中直接使用.vue文件;
- 方式二:自己使用webpack或rollup或vite这类打包工具,对其进行打包处理;
无论是后期我们做项目,还是在公司进行开发,通常都会采用Vue CLI的方式来完成。
6.5.3. 单文件组件(SFC)的插件推荐
官方有推荐一个插件:Volar
如果是使用VSCode开发的话,推荐使用个这个插件,在拓展处搜索volar,点击安装即可。
7.Vue组件化 - CLI脚手架
在真实开发中,我们通常会使用脚手架来创建一个项目,Vue项目我们使用的就是Vue的脚手架;
脚手架其实是建筑工程中的一个概念,在我们软件工程中也会将一些帮助我们搭建项目的工具称之为脚手架;
Vue的脚手架就是Vue CLI:
CLI是Command-Line Interface, 翻译为命令行界面;
我们可以通过CLI选择项目的配置和创建出我们的项目;
Vue CLI已经内置了webpack相关的配置,我们不需要从零来配置;
7.1. Vue CLI的安装
我们可以使用npm(山淼大佬写的)来安装脚手架,可能需要先安装node。
如果之前用过npm,就可以在终端使用命令行来安装脚手架了。
如果使用VSCode开发的话,终端可以按ctrl+shift+`来创建。
7.1.1. 安装Vue CLI
我们是进行全局安装(-g代表global全局),这样在任何时候都可以通过vue的命令来创建项目;
npm install @vue/cli -g
安装成功(目前最新的版本是5.0.8)。
7.1.2. 升级Vue CLI
比较老的版本可以通过下面的指令升级。
npm update @vue/cli -g
7.2.Vue CLI 创建项目
通过Vue命令来创建项目
Vue create 创建的项目名
babel就是将es6转成es5语法;eslint就是对代码进行格式检测。
按键盘的空白键就是选择,a键全选,i键全不选,enter键下一步。
- 刚学习CLI的基础阶段暂时就选择Babel。
- 选择3.x的版本。
- 选择放到独立的文件里面。
- 下面会询问是否要将刚才的配置设置为预设,y/N
- 输入想要生成预设的名字,就开始搭建项目了。
这样就代表创建完成了。
7.3.Vue CLI 运行项目
- 去到项目目录里面,使用npm run serve指令运行项目。
cd 项目目录
npm install
npm run serve
- ctrl+单击就可以点击开链接,进入到Vue默认创建的页面。
7.3.1.项目的目录结构
在创建完项目之后有很多目录结构,图中有每个文件的作用。
7.4.使用Vue CLI的代码编写模式
创建完文件了,好像不会用了,之前学习的内容不知道怎么应用。
- 在script标签里面直接编写data、computed、component等属性,再把这个对象默认传递出去export default。
<!-- App.vue -->
<template>
<h2>{{message}}</h2>
</template>
<script>
export default {
data() {
return {
message: "message"
}
}
}
</script>
<style>
</style>
- 在main.js里面引入App.vue文件。
//main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
7.5. VSCode快速生成vue代码
我们在练习Vue的过程中,有些代码片段是需要经常写的,我们在VSCode中我们可以生成一个代码片段,方便我们快速生成。
VSCode中的代码片段有固定的格式,所以我们一般会借助于一个在线工具来完成。
具体的步骤如下:
- 第一步,复制自己需要生成代码片段的代码;
<template>
<div>AppContent</div>
</template>
<script>
export default {
data() {
return {
}
}
}
</script>
<style scoped>
</style>
- 第二步,https://snippet-generator.app/在该网站中生成代码片段;
将右边生成的内容复制。
- 第三步,在VSCode中配置代码片段;
打开VSCode,菜单栏=>文件=>首选项=>用户片段(或者配置用户代码片段);
把复制的代码粘贴进去;
这样在vue页面输入vue的时候就会生成对应的代码片段了。
写的内容太多了,编辑起来的时候文字都有延迟了,所以在另外一篇文章继续。Vue的认识到应用(二)_至尊绝伦的博客-CSDN博客