原文链接(格式更好):《3-1 Vue 基础》
MVVM
M:Model-数据和业务逻辑
V:View-界面
VM:View Model-桥梁,同步 View 与 Model 之间的数据以及处理用户交互
这种模式下,UI 与业务是分开的
Vue 是如何利用 MVVM 思想进行开发的呢?
双向绑定
- 使用
{{}}构建数据与视图的双向绑定 - 支持视图绑定事件来更改数据
Vue 工程项目
每一个.vue文件就是一个vue 实例,里面分为tcs:template、css(style)、script
项目入口处是对 Vue 的实例化
new Vue({
el: '#app',
// ......
})
生命周期
建立:beforeCreate => created => beforeMount => mounted
更新:beforeUpdate => updated
销毁:
Vue2:beforeDestroy => destroyed
Vue3:beforeUnmount => unmounted
beforeCreate:数据/事件初始化之前。常用于设置默认数据、初始化事件监听器
created:数据/事件初始化之后,挂载之前,可以通过this拿到data、props、methods等值,常用于获取接口数据、设置计时器等
beforeMounted:模板编译之后,DOM 挂载之前,在此可以操作模板/vDom或获取接口数据
vDom:虚拟 DOM,是一个 JS 对象,用来模拟真实 DOM,主要是为了最小化的进行页面渲染
Vue 中获取虚拟 DOM:this.$el
mounted:DOM 挂载之后,在此可以操作 DOM
beforeUpdate:vDom更新后,DOM 更新前,可以操作数据
updated:DOM 更新后,谨慎操作数据,容易出现死循环
beforeDestroy:实例销毁之前,还可以用this
destroyed:实例销毁之后,不可以用this
定向监听
以下两个都是用于响应数据变化的,当依赖发生改变时会触发
computed
一般用于复杂的计算,并且其值可以直接用this.xx获取,但不支持异步操作
多入单出:监听多个依赖,但产出一个变化的值
computed: {
sum(){
return this.count + 1
}
}
watch
一般用于异步操作:获取数据等
单入多出:监听一个依赖,可以触发多个值的改变
watch: {
count() {
this.sum = this.count + 1
},
'obj.key1'(newValue, oldValue) { // 复杂类型的监听
this.sum = this.obj.key + 1
},
'obj.key2': { // 复杂类型的监听
handler() {
this.sum = this.obj.key + 1
},
imediate: true // 是否在该监听器绑定的时候(组件实例初始化阶段)立即执行一次回调函数,默认为 false。
deep: true // 是否深度监听(即监听对象内部属性的改变),默认为 false。
}
}
常用指令
条件
v-if、v-else-if、v-else、v-show
v-if:当为 false 时,DOM 不会渲染到 HTML 中,所以就隐藏了。当值变化不频繁时,用它更好
v-show:当为 false 时,DOM 会渲染到 HTML 中,然后再用 display: none,才隐藏了。当值变化频繁时,用它更好
v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。
<template>
<div v-if="flag">xxx</div>
<div v-show="flag">xxx</div>
</template>
循环
v-for...in + key
<template>
<div v-for="num in 10" :key="num">{{ num }}</div> <!-- num 为:0-9 -->
<div v-for="(value, key) in obj" :key="key">{{ key }}: {{ value }}</div>
<div v-for="(value, index) in array" :key="index">{{ index }}: {{ value }}</div>
</template>
其他
v-once:只渲染一次,渲染后就当成静态节点处理
v-text:作为纯内容,替换节点内容
v-html:作为 html,替换节点内容
v-bind:属性绑定,简写:
v-on:事件绑定,简写@,支持修饰符.stop、.prevent、.capture、.self、.once等
v-model:双向绑定,常用于表单控件上,支持修饰符.trim、.number、.lazy等,通过:value + @input实现
扩展
HTML5
HTML5:是 HTML 规范的一个版本
HTML5 里面新增
- 语义标签:、、 等标签
- 多媒体标签:(视频)、(音频)
- 图形绘制:Canvas、SVG
- Web 存储:LocalStorage、SessionStorage
面试题
v-for 与 v-if 的优先级
Vue2 中:当v-if与v-for一起使用时,v-for具有比v-if更高的优先级。
Vue3 中:当v-if与v-for一起使用时,v-if具有比v-for更高的优先级。
<template>
<div class="hello">
<div v-for="(item,index) in list" v-if="index === 9" :key="item" ></div>
</div>
</template>
<script>
export default {
data(){
return {
list:[1,2,3,4,5,6,7,8,9,10] //需要遍历的数据
}
}
};
</script>
<style scoped>
</style>
在 Vue2 中实际情况如下:
this.list.map((item, index) => {
if(index === 9) {
return item
}
})
// 所以我们只想渲染下标为 9 的,但每次数据改变时都会将整个数据循环一遍,开销大。推荐使用计算过的
// 数据去渲染(可以通过 computed 实现)
在 Vue3 中实际情况如下:
if(index === 9) {
this.list.map((item, index) => {
return item
}
})
// 并且 Vue 报警告
[Vue warn]: Property "index" was accessed during render but is not defined on instance.
官方推荐写法:分开写!!!
Vue 中 key 的作用
提高渲染性能,通过唯一的 key 可以更快速的分辨哪些改变了,哪些没改变,这样最大程度的减少和复用 DOM 操作。
Vue 中写 JSX 与模板有什么区别?
模板编译原理是:
template => 语法匹配 -- 生成AST(标记静态/动态) -- 可执行方法 => render() => dom
在 template 到 render() 之间,Vue 会去做相应的编译优化
JSX编译原理是:
render() => dom
直接写 JSX 是没有任何优化的,这样只要其中的一个变量变化了,整个 render 函数都会重新执行
vue2 的 data 为什么是个函数?
在 Vue 2 中,data 是一个函数,主要是出于以下几个原因:
1. 组件的复用
当你要在多个地方使用同一个组件时,如果你把 data 直接定义为对象,那么每次实例化这个组件时都会创建一个新的对象,这就意味着所有实例都会共享同一个数据对象,一个组件的更改会影响到所有使用这个组件的地方。而通过把 data 定义为函数,每次实例化组件时都会调用这个函数,从而返回一个新的独立的数据对象,这样就能保证每个实例都有自己的数据,互不干扰。
2. 更好的封装
通过将 data 定义为函数,你可以隐藏组件的内部状态,使其更难被外部修改。这对于封装和隐藏实现细节非常有帮助。
3. 代码的整洁
将 data 定义为函数可以让你将相关的逻辑(例如数据的初始化和设置)集中在一个地方,这样代码会更加整洁和易于维护。
4. 响应性系统
Vue 的响应性系统依赖于对数据对象的依赖关系。通过将 data 定义为函数,可以确保每次返回一个新的数据对象时,Vue 的响应性系统都能正确地检测到变化并更新相关的视图。
总的来说,将 data 定义为函数是为了实现更好的组件封装、复用性、代码整洁以及与 Vue 的响应性系统更好地配合(文心大模型3.5生成)