VUE 基础

注意:文中的 vm 为 var vm = new Vue() ,可以在内外部通过vm引用,也可以在内部通过this指向

内在

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter

  1. Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 仅支持IE9及以上版本浏览器的原因。
  2. 因此初始化实例时不在data中的属性不会自动转换为响应式。且Vue 不允许动态添加根级响应式属性。在初始化实例前应声明所有根级响应式属性,即使为空。

Vue 在更新 DOM 时是异步执行的。在每一个事件循环中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。
如果此时你想要根据更新的 DOM 状态去做某些事情,可以使用Vue.nextTick(callback)vm.$nextTick()

指令 (Directives)

通常带有 v- 前缀,通过:传入参数 , 通过.添加修饰符 , 其值(如有)应为单个 JavaScript 表达式。(且可访问到Date,Math等特定的全局变量)指令的职责是,将表达式值的变化更新作用于 DOM。不同于angular.js,在vue中指令和组件是完全不同的两个概念。

  • v-text 更新元素的 textContent。
  • v-once 仅进行首次渲染
  • v-show
  • v-if / v-else-if / v-else
  • v-for
  • v-model
  • v-html 请勿对用户提供的内容使用该指令,易导致xss攻击
  • v-slot 提供具名插槽或需要接收 prop 的插槽。
  • v-bind 操作dom属性,可缩写为:。对于布尔型特性 ,由于只要出现就意味着值为 true,因此若为nullundefinedfalse,vue直接不渲染该属性。
  • v-on 监听dom事件,可缩写为@
    • 从 2.6.0 开始,可以用方括号传入字符串null作为指令参数。字符串不能有空格和引号,且会自动转为小写。null可用于移除绑定。
<a v-bind:[attributeName]="url"> ... </a>
<a v-on:[eventName]="doSomething"> ... </a>
  • v-pre 对其中的{{...}}不进行编译
  • v-cloak 这个属性会保持在元素上直到关联实例结束编译,通常通过以下代码实现防抖
[v-cloak] {
  display: none;
}
...
<div v-cloak>
  {{ message }}
</div>

计算属性 和 侦听器

定义计算属性 和 侦听器时,均不应使用箭头函数

计算属性

计算属性应处于computed中,每当计算属性的相关响应式依赖发生改变,则重新求值。
直接在模板语法中执行函数也可以达成该效果,但需注意的是,函数每当Vue对UI进行update时,都会重新执行,因此性能开销会大于计算属性。好处在于非响应式依赖变更时,函数值也会随着页面渲染而更新。

页面第一次加载时,两个值相同。
str发生更新,两值同步更新。
trigger1更新,此时页面重新渲染,{{computedFun()}}更新,而{{computedData}}不变。
trigger2更新,两值都不变。

{{computedData}}
{{computedFun()}}
{{trigger1}}

data:{
  str : "当前时间是:",
  trigger1 : false,
  trigger2 : false
},
computed: {
  computedData: function () {
    return this.str + new Date()
  },
  computedData2: vm => vm.str + new Date()
},
methods: {
  computedFun(){
    return this.str + new Date()
  }
}
侦听器

侦听器可以达到与计算属性相同的效果
需要监听对象某个属性时,可以直接将对象.属性作为key,或将deep设为true

  watch: {
    str: function (val,oldVal) {
      this.watchedData = val + new Date()
    },
    str2: "someMethod",
    "obj.key": function (val,oldVal) {
      ...
    },
    obj2: {
      handler: "someMethod",
      deep: true,//该回调会在被侦听的对象的任何 property 改变时触发,不论嵌套多深
      immediate: true//侦听绑定后(created之前)立刻生效,此时old值为undefined,新值为data中值
    }
  }

侦听器每次只能侦听一个值,如果需要同时侦听多个,可配合computed使用

computed: {
  tempData: function () {
    const { param1 , param2 } = this;
    return { param1 , param2 } 
  }
},
  watch: {
    tempData: function (val) {
      ...
    }
  }
计算属性的getter和setter

计算属性默认为getter方法,也可以给予一个包含get和set方法的对象,当主动设置计算属性值时就会触发setter

computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

Class与Style

class有两种绑定方式

  1. 对象语法 :class="{ 'className' : true , 'className2' : false}"
    (值为 truthy 即可,不一定需要为true)
  2. 数组语法 :class="[ 'className1' , 'className2' ]"
    注:对自定义添加的class,和该组件本身根元素的class,会取并集

style也有两种绑定方式

  1. 对象语法 :style="{ 'background-color' : 'red', fontSize: 15 + 'px' }"
  2. 数组语法 :style="[{ 'background-color' : 'red' }],[{ fontSize: 15 + 'px' }]"
    注:对需要加浏览器前缀的CSS属性,vue会自动检测并添加,如transform

条件渲染

值为 truthy 即可,不一定需要为true

v-if / v-else-if / v-else
  1. key管理可复用的元素
  2. 可以用template当做不可见的包裹元素,并在上面使用 v-if。
<template v-if="loginType === 'username'">
  <label>Username</label>
  <input key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input key="email-input">
</template>

注:不要把 v-if 和 v-for 同时用在同一个元素上。(因 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,因此每当页面渲染时不管数组是否发生变化都进行了一次map,不利于性能。)

v-show

v-show不支持template, 有较高的初始渲染开销和较低的切换开销。

列表渲染

  • 支持 (均可以为计算属性或一个方法的返回值)
    1. 数组
    2. 对象
    3. 整数(会把模板重复对应次数)
  • 建议使用key追踪每个节点的身份
  • 类似v-if也可以用<template>来循环渲染一段包含多个元素的内容。

v-for="item in items" 或 v-for="item of items"
v-for="(item, index) in items"
v-for="(value, name, index) in object"

通过以下方式变更数组/对象无法触发视图更新
  1. 利用索引直接设置一个项时,例如:vm.items[index] = newValue
  2. 修改数组的长度时,例如:vm.items.length = newLength
  3. 对象属性的新增或删除
  4. 利用 Object.assign() 或 _.extend() 直接赋值

可通过以下方法解决

Vue.set(vm.target, attrToChange, newValue)
vm.$set(vm.target, attrToChange, newValue)

数组也可以通过splice方法解决

vm.items.splice(indexOfItem, 1, newValue)
vm.items.splice(newLength)

另外如使用Object.assign()_.extend()时,参考如下

Object.assign(vm.userProfile, {age: 27}) //无效
vm.userProfile = Object.assign({}, vm.userProfile, {age: 27}) //有效
组件列表
  • 组件上使用v-for时,必须传入key
  • 迭代数据不会自动传入组件,需要依赖prop
<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index"
  v-bind:key="item.id"
></my-component>

事件处理

  • 通过$event可以把原生DOM事件传入方法
事件修饰符

修饰符可以串联,且其顺序决定了逻辑代码的顺序

  • .stop 阻止继续传播
  • .prevent 阻止默认事件
  • .capture 添加事件监听器时使用事件捕获模式
  • .self 仅当 event.target 是自身时触发,不会被子元素触发
  • .once 仅执行一次
  • .passive (2.3.0 新增) 对应addEventListener 中的 passive 选项,可以提升移动端的性能。会覆盖.prevent
按键修饰符

可以将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。如.enter , .tab , .delete (捕获“删除”和“退格”键) , .esc , .space , .up , .down , .left , .right, .ctrl, .alt, .shift, .meta(windows键或command键)以及鼠标按键.right , .left, .middle

<input v-on:keyup.enter="submit">
<input v-on:keyup.page-down="onPageDown">

也可以通过config.keyCodes自定义按键修饰符

// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
  • 2.5.0 新增.exact修饰符
    允许控制由精确的系统修饰符组合触发的事件
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

表单输入

v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:

  • text 和 textarea 元素使用 value 属性和 input 事件;
  • checkbox 和 radio 使用 checked 属性和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。

通常情况下v-model 绑定的值是静态字符串或布尔值,但如果使用v-bind:value则也可以传入其他类型

复选框

单个复选框可绑定到布尔值,或通过true-valuefalse-value绑定其他属性。多个复选框时则可通过value绑定到数组

<input type="checkbox" id="checkbox" v-model="checked">
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no">

<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
...
checked : false
toggle : "no"
checkedNames: []
修饰符
  • .lazy 在“change”时而非“input”时更新
  • .number 将输入值转为number类型
  • .trim 自动过滤收尾空白字符

生命周期

new Vue()时依次执行breforeCreatecreatedbeforeMountmounted

  • breforeCreate
    此时不存在this.$eldatamethods也都拿不到
  • created
    此时不存在this.$el,但可以拿到datamethods。获取数据可以放在该阶段
  • beforeMount
    必须有 el: '#app'才会触发,此时this.$el指向html中书写的内容,但并未经过vue处理,如<div>{{loading}}</div>
  • mounted
    必须有 el: '#app'才会触发,此时this.$el指向渲染后的模板内容,如<div>true</div>

beforeCreate ->inject -> Props -> Methods -> Data -> Computed -> Watch ->provide-> created

  • errorCaptured
    在捕获一个来自后代组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。
    此钩子可以返回 false 以阻止该错误继续向上传播(所有的错误本应发送到应用级的 app.config.errorHandler)。

  • beforeUpdate(不会在SSR中调用)
    在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用。

  • updated(不会在SSR中调用)
    在组件因为一个响应式状态变更而更新其 DOM 树之后调用。

  • activated
    若组件实例是 <KeepAlive> 缓存树的一部分,当组件被插入到 DOM 中时调用。

  • deactivated
    若组件实例是 <KeepAlive> 缓存树的一部分,当组件从 DOM 中被移除时调用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容