Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的渐进式 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。
真实DOM:
浏览器渲染的过程主要包括以下五步:
虚拟DOM指的就是将真实的DOM树构造为js对象的形式,从而解决浏览器操作真实DOM的性能问题。
虚拟DOM就是利用js运行速度快的这一优点对操作DOM进行优化的,用js模拟DOM树,在js中处理DOM的操作再渲染,简单概括分为以下三点:
diff 算法是一种通过同层的树节点进行比较的高效算法。
Vue实例化对象挂载到根元素后,生成全局Vue对象实例,Vue对象在实例化过程中会传入配置对象(options),options中包括data、methods、computed、watch等等
模板语法分两类:文本插值语法与指令语法。
<div>{{xxx}}div>
//xxx 是 js 表达式,可以直接读取到 data 中的所有区域
v-html
:插入为html;<span v-html="xxx">span>
v-bind
:单向数据绑定,数据只能从data流向页面;<div v-bind:id="dynamicId">div>
简写为:
<div :id="dynamicId">div>
动态绑定多个值:
<div v-bind="objectOfAttrs">div>
data() {
return {
objectOfAttrs: {
id: 'container',
class: 'wrapper'
}
}
}
v-model
:双向数据绑定,数据不仅能从data流向页面,也能从页面流向data;把v-model:value
简写为v-model
;常用于表单类组件。<input type="text" v-model:value="name"><br/>
简写为
<input type="text" v-model="name">
v-if
: 该指令会基于表达式的值的真假来移除/插入该元素<p v-if="seen">Now you see mep>
v-on
:监听DOM事件,缩写为@
字符<a v-on:click="doSomething"> ... a>
<a @click="doSomething"> ... a>
动态参数:
同样在指令参数上也可以使用一个 JavaScript 表达式,需要包含在一对方括号内:
<a v-bind:[attributeName]="url"> ... a>
<a :[attributeName]="url"> ... a>
data:选用选项式 API 时,会用 data 选项来声明组件的响应式状态。此选项的值应为返回一个对象的函数。Vue 将在创建新组件实例的时候调用此函数,并将函数返回的对象用响应式系统进行包装。此对象的所有顶层属性都会被代理到组件实例 (即方法和生命周期钩子中的 this) 上。
也就是,data是在创建vue实例时调用的函数,该函数返回响应式组件中要响应的值构成的对象,该对象的顶层属性与组件实例挂钩。
data有2种写法:
el:
el有2种写法
MVVM模型
data中所有的属性,最后都出现在了vm身上;
vm身上(即Vue实例)所有的属性 及Vue原型身上所有的属性,在 Vue模板(页面的大双括号)中都可以直接使用。
数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
Object.defineproperty(给谁加属性,属性名,{配置项})
配置项:
{
value:xx,
enumerbale:true,//是否可枚举,默认false
writable:true,// 是否可以被修改,默认值是false
configurable:true// 是否可以被删除,默认值是false
get(){}
//当有人读取对象的该属性时,get函数(getter)就会被调用,且返回值就是该属性的值
set(value){}
//当有人修改对象的该属性时,set函数(setter)就会被调用,且会收到要修改的值
}
Vue中的数据代理:
也就是说,我们创建vue实例时传入配置项,其中data函数返回了一组数据,该数据被拷贝到实例(vm)中的_data
中,然后再用data函数中的数据代理_data
中的数据。_data
为了实现数据劫持,实现数据更改监听,通知vue去渲染。
Vue2中写到:
当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
data有两种写法,但他到底是对象还是函数呢
事件修饰符:
修饰符可以连用:@click.prevent.stop=dosome
键盘事件:
属性:data里的数据,前者为属性名,后者为属性值。
定义:要用的属性不存在,需要通过已有属性计算得到。
原理:底层借助了Objcet.defineproperty()方法提供的getter和setter。
getter在初次读值和依赖的数据改变时会调用。
setter在该属性被修改时会调用。
优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便 。
计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算。否则立即返回先前的计算结果,而不用重复执行 getter 函数。方法调用总是会在重渲染发生时再次执行函数。
语法:
computed{
计算属性名:
{ get(){},
set(){}}
}
new Vue({
el:'#root',
data:{
n:12
},
computed: {
//完整写法
fun: {
get(){
return n++;
},
set(value){
this.n=value
}
// 简写
fun2() {
return this.n++
}
}
})
计算属性是直接从已有属性计算得到“新属性”,但如果需要对已有属性进行一些衍生操作,就无法完成。
监视属性是每次响应式属性发生变化时触发一个函数。在要监视的已有属性发生变化时,触发函数进行一些操作。
watch监视属性
监视有两种写法
const vm = new Vue({
el: '#root',
data: {
isHot: true,
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
// 方式一
/* watch:{
isHot:{
immediate:true,
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}
} */
})
// 方式二
vm.$watch('isHot', {
immediate: true, // 初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时
handler(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue)
}
})
多级监测:
监测对象中某个值,直接使用引号'对象名.属性名'
const vm = new Vue({
el: '#root',
data: {
number:{
a:1,
b:2
}
},
watch:{
"number.a":{
immediate:true,
handler(newValue,oldValue){
}
}
}
})
深层监测器:
watch 默认是浅层的:被侦听的属性,仅在被赋新值时,才会触发回调函数——而嵌套属性的变化不会触发。如果想侦听所有嵌套的变更,你需要深层侦听器。
deep:true
可以监测对象内部值的改变(多层)注意
简写:
如果监视属性除了handler没有其他配置项的话,可以进行简写。
watch: {
//简写
isHot(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue, this)
}
计算属性 VS 侦听属性
computed能完成的功能,watch都可以完成
watch能完成的功能,computed不一定能完成,例如watch可以进行异步操作
所有被Vue管理的函数,最好写成普通函数,这样 this 的指向才是vm或组件实例对象
所有不被Vue所管理的函数(定时器的回调函数、ajax 的回调函数等、Promise 的回调函数),最好写成箭头函数,这样 this 的指向才是vm或组件实例对象
数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式,使用v-bind
。
绑定数组
<div :class="[activeClass, errorClass]">div>
绑定对象isActive
<div :class="{ active: isActive }">div>
<div class="basic" :class="mood" @click="changeMood">{{name}}div><br/><br/>
<div class="basic" :class="classArr">{{name}}div><br/><br/>
<div class="basic" :class="classObj">{{name}}div><br/><br/>
<div class="basic" :style="styleObj">{{name}}div><br/><br/>
<div class="basic" :style="styleArr">{{name}}div>
v-if
指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值时才被渲染。一个 v-else
元素必须跟在一个 v-if
或者 v-else-if
元素后面,否则它将不会被识别。
想要切换不止一个元素:在这种情况下我们可以在一个 元素上使用 v-if,这只是一个不可见的包装器元素,最后渲染的结果并不会包含这个 元素。
v-show
也会条件显示一个元素。
<h1 v-show="ok">Hello!h1>
v-if 与 v-for:
使用 v-for 指令基于一个数组来渲染一个列表。
,这里key可以是index,更好的是遍历对象的唯一标识“(item, index) of items” :key=“index”:
遍历对象:第一个是属性值,第二个属性名,第三个是位置索引;
遍历数组:item in items
<li v-for="item in items">
{{ item.message }}
li>
<!-- 遍历数组 -->
<h3>人员列表(遍历数组)</h3>
<ul>
<li v-for="(p,index) of persons" :key="index">{{ p.name }}-{{ p.age }}</li>
</ul>
<!-- 遍历对象 -->
<h3>汽车信息(遍历对象)</h3>
<ul>
<li v-for="(value,k) of car" :key="k">{{ k }}-{{ value }}</li>
</ul>
<!-- 遍历字符串 -->
<h3>测试遍历字符串(用得少)</h3>
<ul>
<li v-for="(char,index) of str" :key="index">{{ char }}-{{ index }}</li>
</ul>
<!-- 遍历指定次数 -->
<h3>测试遍历指定次数(用得少)</h3>
<ul>
<li v-for="(number,index) of 5" :key="index">{{ index }}-{{ number }}</li>
</ul>
v-for 可以直接接受一个整数值。在这种用例中,会将该模板基于 1…n 的取值范围重复多次。
<span v-for="n in 10">{{ n }}span>
注意此处 n 的初值是从 1 开始而非 0。
在 标签上使用 v-for 来渲染一个包含多个元素的块。
不建议同时使用v-for和v-if,因为无法区分优先级。
可以直接在组件上使用 v-for,但不会自动将任何数据传递给组件,因为组件有自己独立的作用域。
key管理:
Vue 默认按照“就地更新”的策略来更新通过 v-for 渲染的元素列表。当数据项的顺序改变时,Vue 不会随之移动 DOM 元素的顺序,而是就地更新每个元素,确保它们在原本指定的索引位置上渲染。
默认模式是高效的,但只适用于列表渲染输出的结果不依赖子组件状态或者临时 DOM 状态 (例如表单输入值) 的情况。
所以需要为每个元素对应的块提供一个唯一的 key,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素。
数组管理:
变更方法:更改原数组
替换数组:返回一个新数组
数据监视:
这个链接中讲解得很清楚:Vue数据监控
简单来说,就是
动态新增的属性:Vue.set(targetObject,attributeName,attributeValue)方法或this.$set(targetObject,attributeName,attributeValue)进行响应式属性的动态添加。
Vue不会为数组元素添加响应式的getter和setter,所以通过下标更改数组数据是无法被Vue所监测到的。
针对数组,只有通过调用push、pop、shift、unshift、splice、reverse、sort这7个改变原数组本身的API,才会引起Vue的响应。