# 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-forv-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">