# 1、表达式{{}}的用法
{{}} 由于当前这个表达式,最终会被编译成函数 _xxx(argument)的形式
1、{{1+1}} 可以写表达式,不能写js语法,因为最终会将返回值,传递给函数 <br>
2、{{msg === 'hello'? true:false}} 可以写三元运算符<br>
3、{{fn()}} 可以写函数执行,会把执行后的结果传递给函数<br>
4、{{msg. b}} 或者写参数的形式
# 2、响应式规则
let vm = new Vue({
el:'#app',
data(){
return {msg:{a:1},arr:[1,2,{a:1}]}
}
})
// vm. $set(vm. arr, 0, 100); // 内部采用的就是splice方法
// vm. $delete(vm. arr, 0);
vm. arr[2]. a = 100;
- 会递归的去循环vue中的属性**(Vue2. 0浪费性能的地方)**(在3. 0中通过proxy得到了有效的解决) 会给每个属性都增加getter和setter,当属性变化时会更新视图
- 重写了数组中的方法,当调用数组方法时会触发更新, 也会对数组中的每一项进行了监控
- 易错点:对象只监控了默认自带的属性, 新增属性是不生效的
例如:
let vm = new Vue({
el:'#app',
data(){
return {msg:{a:1}}
}
})
// 要通过这样的方式去修改新增属性,需要给定msg. b的初始值
vm. msg. b = 100;
// 否则就需要使用 vm. $set(vm. msg, b , 100) 来修改
# 3、如何用proxy来实现响应式原理
对象的深度监控以及数组的api
proxy与Object. defineproperty的异同
Object. defineproperty只能拦截对象中的某一属性 proxy则代理,拦截的是整个对象(// 兼容性差 可以代理13种方法 set get)
核心:Reflect 反射 这个方法里包含了很多的api
# 对象的深层递归代理
let obj = {
name: {
name: 'jw'
},
}
// target:原对象 key:当前取的是那个值
let handle = {
get(target, key) {
console.log('收集依赖') // 拦截 代理
if(typeof target[key] === 'object' && target[key] !== null) {
return new Proxy(target[key])
}
return Reflect.get(target, key) // target[key]
},
set(target, key, value) {
console.log('触发更新')
// target[key] = value // 设置时 如果不成功,不会报错,对象不可配置
return Reflect.set(target, value)
}
}
let proxy = new Proxy(obj, handler)
// 懒代理
proxy. name. name
# 数组的深层递归代理
注意
数组在set时,会先更改索引,再更改长度,具体见下面例子
let obj = {
arr: ['吃', '喝', '玩']
}
let handle = {
get(target, key) {
console.log('收集依赖') // 拦截 代理
if(typeof target[key] === 'object' && target[key] !== null) {
return new Proxy(target[key])
}
return Reflect.get(target, key) // target[key]
},
set(target, key, value) {
// 判断一下 当前是新增操作,还是修改操作
let oldValue = target[key]
if(!oldValue) {
console.log('新增属性')
} else if (oldValue !== value) {
console.log('修改属性')
}
return Reflect.set(target, value)
}
}
let proxy = new Proxy(obj, handler)
// 懒代理
proxy. arr. push(123)
// key oldValue value
// 3 undefined 123
// length 4 4
proxy. arr[0] = 100
// key oldValue value
// 0 吃 100
# 4、vue中常见实例属性
let vm = new Vue({
//el:'#app',
template:'<div>{{msg}}</div>',
data(){
return {msg:'hello'}
}
})
//
vm. $mount(); // 挂载 如果不传递参数 表示我要手动挂载, 可以挂载到页面的任何地方,以前的写法只能放到app中
vm. $mount('#app'); // 表示挂载到app中
document. body. appendChild(vm. $el); // 将渲染的template模板挂载到body上
vm. $options; // 用户传入组件实例的参数所有的选项 和 vue中的内置属性
// queueWatcher
vm. $watch('msg', function (newValue, oldValue) {
console.log(newValue); // 456
})
vm. msg = 'world';
vm. msg = 123;
vm. msg = 456;
watcher的异步更新
watcher的异步批量更新只更新最后一次
原因: 把同一类的watcher收集起来,最后统一触发
# 5、模板指令(列表渲染)
v-html
v-html 容易造成xss攻击(获取用户的cookie),不能讲用户输入的内容回显
v-if与v-show
v-if 控制是否渲染dom结构
v-show 控制dom上的样式, display:none还是display:block
如果用户频繁切换显示隐藏就使用v-show,如果控制dom是否产生就用v-if
v-if可以阻止后续逻辑的发生,v-show则不会,子标签里的逻辑会照常执行
# v-for和v-if一同使用
v-for和v-if不能使用在同一个元素
结果:由于v-for的优先级高于v-if,所以会先遍历,再判断,这样导致性能浪费
v-for如果放在template上 必须将key放到真实元素上
# 法一:在外层使用v-if,内层使用v-for
<ul v-if="todos. length">
<li v-for="todo in todos">
{{ todo }}
</li>
</ul>
# 法二:计算属性 先算完之后 再去遍历
# 6、key的取值问题
注意
尽量不要使用索引,使用索引会导致index值被重复定义,导致报错!
应使用变量名的方式区别开,a_${index}, b_${index}
<div v-for="(a, index) in 3" :key="**a_${index}**">{{a}} {{index}}</div>
<div v-for="(a, index) in 3" :key="**b_${index}**">{{a}} {{index}}</div>
# 7、Class与Style如何动态绑定
Class与Style动态绑定
Class和Style都可以通过对象语法和数组语法进行动态绑定
# Class对象语法:
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
> </div>
data: {
isActive: true,
hasError: false
}
结果渲染为:
<div class="static active"></div>
# Class数组语法:
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
渲染为:
<div class="active text-danger"></div>
如果你也想根据条件切换列表中的 class,可以用三元表达式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
当有多个条件时,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
# Style对象语法:
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
# Style数组语法:
v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:
<div v-bind:style="[baseStyles, overridingStyles]"></div>
# 8、v-model的原理?
我们在 vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 元素使用 value 属性和 input 事件;
- checkbox 和 radio 使用 checked 属性和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
以input表单元素为例:
<input v-model='something'>
等价于
<input :value="something" @input="(e) => something = e. target. value">