#【2022.3】尚硅谷Vue.js从入门到精通基础笔记(理论+实操+知识点速查)
前言
本文完全基于 参考资料:加工整理而成,包括其代码,案例,资源等。前置知识是学习尚硅谷的视频教程,本文配合其教程食用,效果更佳。
b站直接搜索 vue ,第一条结果即是:
https://www.bilibili.com/video/BV1Zy4y1K7SH?spm_id_from=333.337.search-card.all.click
目录
一、通用概念、前置知识
1.1 MVC 和 MVVM
大家一说起MVC 都知道,但是和MVVM一对比就搞混了。这里举两个例子搞清楚MVC和 MVVM:
MVC 架构(偏后端,以JavaWeb举例)
该架构就是传统JavaWeb项目开发的一般模式,比较简单。
下面两张图截取自:,详情可直接移步该博客
MVVM架构(偏前端,以Vue举例)
前置知识是你得懂双向绑定:本文下面有讲解双向绑定,先看双向绑定。
一图说清MVVM(图来源自尚硅谷课件,本人进行二次加工):
在代码中体现上图中的Data Bindings(通过VM,将M绑定到View):
在代码中体现上图中的DOM Listeners(通过VM,将V绑定到M):
执行效果:
同时做到了将M绑定到V,和V绑定到M,就是实现了双向绑定。
VM(就是ViewModel),其实就是Vue实例本身,它负责将View和Model绑定起来
这就是Vue的MVVM体现!要理解透彻,需要对ViewModel,双向绑定,Vue实例都有详细的理解。其它前端框架对MVVM有不同的解释,但是原理和思想上是一致的。
最后看维基百科对其的定义:
1.2 WebPack基本概念 和 Vue-CLI
不需要全部学会WebPack这门技术,只是对其有一个基本认知即可。
它依赖于Node,可以使用npm安装;
使用npm init 指令构建 package.json 文件;
webpack 能够编译打包 js 和 json 文件。 能将 es6 的模块化语法转换成浏览器能识别的语法。 生产环境能压缩HTML,CSS,JS代码。
可以打包各种各样的资源:样式资源、图片资源、HTML资源,提取压缩css,js语法检查/兼容性处理。
那Vue-CLI是什么呢?其实就是Vue官方给我们构建的适用于.vue的打包构建工具
1.3 【面试】虚拟DOM(vitural dom)
虚拟DOM是内存中的数据,然后将虚拟DOM变成真实DOM。
原生js(不使用虚拟DOM):
Vue使用虚拟DOM方式:
虚拟DOM的好处:如上图,假如用了虚拟dom的技术,会将虚拟DOM和真实DOM比较(就是上图的diff算法),发现001,002,003是重复的。于是就不会再次渲染001,002,003. 而是复用它们。
只有004的虚拟DOM是不重复的,需要重新渲染。这就提高了展示效率。
虚拟DOM 和 v-for 中的key
v-for 中的 key,下文有提到。
虚拟DOM有一个比较算法,基于什么比较呢?就是基于key
这里直接看对应关系:
在进行渲染时,会将内存中的老虚拟DOM和新虚拟DOM根据key做比较,一旦发现虚拟DOM之间有变化,那么只重新渲染变化部分,复用未变化部分。所以 key 这个属性很重要。
一旦你的结构中包含输入类DOM,会产生错误DOM更新,导致界面渲染有问题。
【面试总结】总结key和虚拟DOM(react也有这概念)
1.4 vue官方文档和API
https://cn.vuejs.org/
官方推荐的Vue组件包:
1.5 双向绑定概念
https://blog.csdn.net/weixin_44757863/article/details/109110132
1.6 常用工具和资源,网站等
bootcdn.cn (收集无数三方库、工具类)
Vs Code 插件:Live Server
该插件真乃神器。内置小型Tomcat,以你在VS中打开的文件夹作为根资源,运行于一个小型的服务器。
该服务器的默认端口号为:5050
如下两张图所示,你就是只写了个HTML,也会给你跑在localhost:5050这个服务器上:
Vs Code 插件:Auto Close Tag
Vs Code 插件:Auto Rename Tag
其它实用VS插件:
JS Quick Console是真神器,快速生成console.log() 它不香吗?
Vue Devtools
在使用 Vue 时,我们推荐在你的浏览器上安装 Vue Devtools。它允许你在一个更友好的界面中审查和调试 Vue 应用。
如何安装:
固定该程序(谷歌浏览器):
二、Vue 基础笔记
1、安装(引入)Vue.js
官网链接:https://cn.vuejs.org/v2/guide/installation.html
- 1.1 原生安装方式:在HTML中使用JS标签引入 可以使用绝对路径和相对路径的方式。如果是绝对路径,就是https://这种直接引入互联网,如果是…/static 这种方式,就可以引入自己下载好的vue.js文件。 举例: - Vue-Cli
2、创建Vue对象,和Vue插值语法{ { xxx }}
下图一图便知:
关于上图的补充细节:
- 1、一个vue实例,只能绑定一个对应实例。这是一对一关系。多了就解析不了。- 2、{ {}} 插值语法,可以写JS表达式。(这点和thymeleaf有点类似)看下图例子:
【补充】el与data的两种写法(Vue实例管理)
el的另外写法如下:
原理是因为调用了原型链上的 $mount
属性:
至于什么是原型链,下面会讲解。现在只需要记住可以使用这种方法来绑定容器即可。
data的另一种写法(函数式)如下:
组件式开发全部都是函数式。该函数必须返回一个对象。
注意,这个函数,只能写成普通函数。如果写成箭头函数,箭头函数的this是window,普通函数的this就是Vue实现对象:
ES语法小课堂:
普通函数的this指向是调用它的那个对象,而箭头函数没有this,如果强制它this,由于无人调用,最终指向的就是window。
ES规范中,如果想在对象中写函数,还可以这样简写(和上图完全就是一个东西,只不过简写了而已):
就如上图那个data()一样,今后我们可以看到由很多由Vue管理的函数(Vue对象会调用它)。凡是由Vue管理的函数,都不能写成箭头函数,给老老实实的写成普通函数!
【补充】创建Vue对象时,其它可配置属性
刚刚只介绍了el和data,这里陆续介绍其他的。
【methods】可以传各式各样的函数
但是这个函数仍然受到Vue管理,所以不能写成箭头函数,只能写成普通函数。
methods是个对象,里面可以传入各式各样的函数。
传入的函数要符合:JS对象的某个属性是函数的语法规则。可以自行搜索JS对象中,如何让其某属性变成一个函数
举例:
methods 中的 event
event在不使用Vue时,可以通过windows.event
调用
在Vue中,如果你不传任何参数,methods中的函数可以自动获取到event:
Vue中,如果你想传一个实参event对象(event为浏览器内置的全局对象),不能直接写event,而是应该写:$event
如果你想用event,有一个【实参】占位符 $event
,可以传入event给形参中:
【重要】methods 调用 data 配置属性
使用this即可。
红色箭头是使用this获取到data的值,但是高明的地方在于蓝色箭头,因为蓝色箭头使用v-model,对data的属性进行了双向绑定,那么input框一旦改变,那么就会引起data改变,data改变从而引起methods里的自定义函数的返回值改变!!
computed 计算属性
watch 监视属性
filters 过滤器
template HTML模板
下图是最简单的用法
3、Vue指令语法
前面在2里面讲了Vue插值语法 { {}},这里讲指令语法。 这一块和thymeleaf更像了,直接在标签上绑定就行。
【v-bind】: 绑定html的标签属性:
v-bind可以直接简写为 : (一个冒号) v-bind: 后面的双引号,和{ {}}插值语法一样,可以写JS表达式。 和thymeleaf一样,v-bind: 可以绑定任何标签。
【v-model】 双向绑定:
https://blog.csdn.net/weixin_44757863/article/details/109110132
补充两个注意事项:
1、如下图 2、v-model:value
的简写就是 v-model
。原因很简单,因为v-model只能应用在表单类(输入类元素)上。
例:
指令语法和插值语法的区别:
插值语法用于标签体,例:
<p>Hello,{<!-- -->{name}}</p>
而指令语法则是直接绑在标签的自定义属性上,例:
<a v-bind:href="defineUrl" v-bind:xxxx="hello">超链接</a>
4、Object.defineProperty方法
更高级的给对象添加属性方式。比原来的person.age这种方法高级的多,可以配置很多详细信息。
用法如下图,更多详细的配置对象属性可以自行百度。
如果设置了不可以枚举【默认就是不可枚举!】,那么就不能用for-each循环遍历对象属性了。
- 常用属性之:enumerable,布尔类型,默认值是false。如果想让该字段可枚举,就要显式设置为true。 - 常用属性之:configurable,布尔类型,默认值是false。控制字段是否可以被删除 - 常用属性之:writable,布尔类型,默认值是false。控制字段是否可以被修改 - 常用属性之:value,就是赋值,赋字段一个值。
常用属性之get和set
get和set这两个属性特别重要,所以单独拿出一节来讲解。
来看下面一个场景:
let number = 18
let person = {<!-- -->
name: "大吉",
sex: "男",
age: number
}
console.log(person.age) //输出18
number = 22 //将number这个变量修改为22
console.log(person.age) //输出仍然是18,而不是22
如果我们想让第二个console.log输出的是22呢?应该怎么操作?
这里就引入了我们强大的get和set功能了!!
- 接上图例子,使用get将输出修改为22:
let number = 18
let person = {<!-- -->
name: "大吉",
sex: "男",
age: number
}
console.log(person.age) //输出18
Object.defineProperty(person, "age", {<!-- -->
get() {<!-- -->
console.log('有人读取了age属性')
return number; //return值很重要
}
})
number = 22 //将number这个变量修改为22
输出的是22。只要有人读取age属性,
就会调用get方法,get方法return的值就是number这个变量
console.log(person.age) //22
执行效果如图所示:
所以我们通过get,实现了只要有人读取age属性,就可以执行get这个方法,至于get这个方法你里面想塞什么都可以。反正只要有人读取age这个属性,就执行get。
- 下面再看set方法:
let number = 18
let person = {<!-- -->
name: "大吉",
sex: "男",
age: number
}
console.log("number的值是:" + number) //18
Object.defineProperty(person, "age", {<!-- -->
//只要有人修改age属性
//就会调用set方法,且会收到修改age属性的具体值
set(value) {<!-- -->
console.log('有人修改了age属性,age:' + value)
//神奇的操作来了,我们让number这个变量修改
number = value;
}
})
person.age = 22 //修改age属性,从而调用set方法
//非常神奇,我们明明修改了age,却能对number做修改
console.log("number的值是:" + number) //22
执行效果图:
总结:通过get和set,使得操作对象更加灵活了
为什么要学这个Object.defineProperty方法呢?是为了下一节数据代理做准备!
5、数据代理(数据劫持)
概念:数据代理就是通过一个对象对另一个对象中属性的操作(读/写)
直接看下图:
上图中如果有人动了obj2,相当于通过obj2动了obj。 这就是最简单的数据代理实例
Vue如何应用数据代理呢?
通过数据代理,我们本应该操作vm._data.属性
,现在我们直接操作vm.属性
即可。
6、事件处理
6.1【v-on】绑定单击事件(结合前面讲的methods一起学习)
其简写是 @ 符号
举例:(下面两种方式等价。)
<button v-on:click="func1">按钮</button>
<button @click="func1">按钮</button>
如果你想传参(当然你的func1的定义处也需要定义形参才可以):
<button v-on:click="func1(a,b,c,d)">按钮</button>
如何将func1和func2被Vue管理呢?移步前文中的methods,一查便知。
6.2事件修饰符
对事件进行操作,前置知识是你得知道JS中的event。
【JS基础之event】
https://blog.csdn.net/lhjuejiang/article/details/79455801
event是一个内置的全局对象,我们看看里面有什么:
<button onclick="func1(event)">按钮</button>
function func1(event) {
<!-- -->
console.log("我是个函数")
console.log(event.target)
}
上面的代码调用了func1,并且传入了全局的event,下面来看event的属性:
event的常用姿势:
event.preventDefault()
它可以阻止默认事件的发生。比如<a>
标签,其默认事件是跳转。如果我们想阻止单击超链接的跳转,可以这么玩儿:
<a href="https://www.baidu.com" onclick="func0(event)">超链接</a>
function func0(event) {<!-- -->
event.preventDefault()
}
此时打开控制台:
event的 defaultPrevent属性默认为false的,现在是true了。现在单击超链接将不会跳转。
回到事件修饰符中来,如果我们想在Vue中实现上述操作,需要怎么做呢?事件修饰符马上登场:
<div id="root">
<a href="https://www.baidu.com" @click.prevent="func00(event)">被Vue管理超链接</a>
</div>
<script>
new Vue({<!-- -->
el: '#root',
data: {<!-- -->
},
methods: {<!-- -->
func00(event) {<!-- -->
console.log("vue阻止页面跳转")
}
}
})
</script>
上面一坨代码,和event.preventDefault() 是一样的效果。
@click.prevent
就是一个事件修饰符。
常用事件修饰符(共六种):
prevent、stop、once、capture、self、passive
stop可以阻止事件冒泡到它的上层; once:once如果作用于按钮或者超链接,那么超链接只有第一次点击的时候 会跳转,除此之外该超链接将不会跳转。
键盘事件
以 @keyup.xxx 当键盘弹起 事件 为例:
有keyup当然就有keydown,当键盘按下立刻触发某事件。 上面的@keyup.esc
就是当esc键弹起,就触发showInfo这个自定义函数(该函数必须受Vue管理,即放在methods中)
其它常用的按键别名: 上图的2 解释:假如你想绑定CapsLock,你应该这样写:@keyup.caps-lock="xxxFunction"
,即转为小写且短横线命名。
【DEBUG:】似乎这里的事件修饰符绑定的函数不可以写 xxxFunction() 后面的小括号。否则会报错。必须把小括号去掉才可以。
7、计算属性(computed)
计算属性要解决的问题
计算属性要解决的问题是:插值语法{ {}} 中,越来越长的JS表达式,不利于阅读和组件化的问题。
来看案例:
计算属性使用案例
计算属性和data联动,同样可以用this。看下例:
上图input框框中的 firstName、lastName 和下图 data中的 firstName、lastName 是双向绑定关系。
input框变化,data也会变。如果此时有人调用 计算属性中的fullName,那么fullName自然会变化。
计算属性中get还有一个属性:只要get里面绑定的data有变化,也相当于调用了一次vm中的 get() ,所以只要data里面的firstName和lastName变了,那么fullName即被调用。
执行效果图:
顺便一提,计算属性的属性也有set,和Object.defineProperty的set用法原理一样,如下图所示
计算属性总结:
为什么叫计算属性?它是根据 data
中,已经有的属性计算得出来的复杂属性。
计算属性简写
当你的计算属性只有人读,没有人修改,(也就是只有get没有set),那么计算属性可以简写为:
上图等价于下面的代码(其实就是简写了get,computed是一个对象,对象的 fullName 字段是一个函数而已):
computed: {<!-- -->
fullName: {<!-- -->
get() {<!-- -->
console.log('get被调用了')
return this.firstName + '-' + this.lastName
}
}
}
8、监视属性(watch)
概念作用:监视属性仍然是监视 data 的属性变化(也可以监视计算属性!)。
监视属性的传值是一个配置对象。
当data里面的某字段发生变化,就调用handler函数,handler函数里面有两个入参,分别是newValue、oldValue,顾名思义代表修改前和修改后。如下图所示:
如果被监视结构是多级的:
data:{<!-- -->
numbers:{<!-- -->
a:1,
b:1
}
}
那么应该这样配置:
watch: {<!-- -->
'numbers.a': {<!-- --> //这样配置多级结构
handler() {<!-- -->
console.log("a被改变了")
}
}
}
监视属性的其它写法:
调用vm的$watch方法:
这种写法可以简写。但是简写的前提是:watch的配置项只有handler一个参数!!!!,不能有什么deep啊,immediate之类的。
简写办法:
监视属性简写
简写的前提是:watch的配置项只有handler一个参数!!!!
immediate :true 初始化时让handler调用一下。 什么immediate 啊,deep啊,都不能写,才能用这个缩写。
深度监视
深度监视是默认关闭的。
场景如下:
如果被监视结构是多级的:
data:{<!-- -->
numbers:{<!-- -->
a:1,
b:1
}
}
如果你想监测 numbers.a 的变化,上文已经讲过如何监视了。这里不做讲解。但是如果a变化了,那么numbers应该是也变化的。但是Vue却不认为numbers变化了!此时你再监视numbers,假如numbers.a被修改,那么Vue不认为numbers被修改。
如下所示:
watch: {<!-- -->
numbers: {<!-- -->
handler() {<!-- -->
//就算numbers.a变了,下一句也不会执行
console.log("numbers被改变了")
}
}
}
解决方案:打开深度监视:
watch: {<!-- -->
numbers: {<!-- -->
handler() {<!-- -->
deep:true, //开启深度监视
//numbers.a变了,下一句会执行
console.log("numbers被改变了")