Vue自习手册——基础

256 阅读9分钟

用于记录对Vue官方教程的学习

更新日志

指令

由于之前看过部分某马的视频,有一点点映像,所以在一开始就将指令先复习了一遍

# v-text

  • 更新元素的 textContent
  • 如果只更新部分 textContent ,需使用插值表达式

# v-html

  • 更新元素的 innerHTML

# v-show

  • 根据表达式真假,切换元素的 display CSS属性
  • 条件变化时该指令触发过渡效果

# v-if

  • 根据表达式真假,切换元素渲染状态
  • 条件变化时,该指令触发过渡效果

如果元素会被频繁切换显示/隐藏状态,用v-show有更好的性能 与v-for共在时,v-for优先级更高

## v-else

  • 前一兄弟元素必须有 v-ifv-else-if
  • 前一个 v-ifv-else-if 表达式为假时,渲染当前元素

## v-else-if

  • 前一兄弟元素必须有 v-ifv-else-if
  • 前一个 v-ifv-else-if 表达式为假时,且,当前表达式为真时,渲染当前元素

# v-for

  • 根据元数据的项数,多次渲染当前元素
    // 基本使用
      v-for="item in items"
    // 扩展使用
      v-for="(item ,index) in items"
      v-for="(val ,key) in object"
      v-for="(item ,index) in items"
      
    
  • 使用 v-for 时,同时给元素绑定 key会有更好的性能(这里涉及到之后的知识)
      v-for="item in items" :key="item.id"
    

# v-on

  • 缩写:@
  • 绑定事件监听器
  • 用法:v-on:事件="方法名"
  • 修饰符
    • .stop - 调用 event.stopPropagation() - 停止冒泡
    • .prevent - 调用 event.preventDefault() - 阻止默认行为
    • .once - 只触发一次回调
    • .left - 只鼠标左键触发
    • .right - 只鼠标右键触发
    • .middle - 只鼠标中键触发
    • 修饰符可以串联

# v-bind

  • 缩写::
  • 动态绑定数据到属性上
  • 用法:v-bind="data中的数据名"
  • 内联字符串拼接 - <img :src="'/path/to/images' + fileName"
  • class绑定
    <div :class="{red: isRed}"></div>
    <div :class="[classA ,classB]"></div>
    <div :class="[classA ,{classB: isB ,classC: isC}]"></div>
    

# v-model

  • 限制:
    • input
    • select
    • textarea
    • components
  • 在表单控件或组件上创建双向绑定

# v-slot

  • 看了组件-插槽就明白了

# v-pre

  • 跳过这个元素和它的子元素的编译过程

# v-cloak

  • 隐藏未编译的元素,直到元素编译完毕
  • 用法: 配合CSS使用 [v-cloak]{display:none}

# v-once

  • 只渲染元素和组件一次

选项/数据

# data

  • 类型:Object | Function
  • 限制:组件的定义只接受function
  • 详细:
    • Vue实例的数据对象
    • 实例创建后,可以通过vm.$data访问原始数据对象
    • Vue实例也代理了data对象上所有属性,因此vm.a等价于访问vm.$data.a
    • _$开头的属性不会被Vue实例代理,使用vm.$data._property访问这些属性
    • 当一个组件被定义,data必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果data仍是一个纯粹的对象,则所有实例共享引用同一个数据对象!!!通过提供data函数,每次创建一个新实例后,能够调用data函数,从而返回初始数据的一个全新副本数据对象
    • 如需要,可通过将 vm.$data 传入 JSON.parse(JSON.stringify(...)) 得到深拷贝的原始数据对象

Vue实例

  • 每个Vue应用都是通过用 Vue 函数创建一个新的Vue实例开始的:
    var vm = new Vue({
      // 选项/数据
    })
    
  • 一个Vue应用由一个通过 new Vue 创建的根Vue实例,以及可选的嵌套的、可复用的组件树组成。
  • 当实例中的数据改变时,视图会进行重渲染(只有当实例被创建时就已经存在于data中的属性才是响应式的。
  • 使用Object.freeze(obj)可以防止obj中的属性被修改
  • 除了数据属性,Vue实例还暴露了一些有用的实例属性与方法(以前缀$开头)
    var vm = new Vue({
      el: '#example',
      data: { a: 1 }
    })
    vm.$data === data
    vm.$el === document.getElementById('example')
    vm.$watch('a',function(newValue, oldValue){
      // 这个回调将在'vm.a'改变后调用
    })
    

# 实例生命周期钩子

每个Vue实例在被创建时会经过一系列的初始化过程,在这个过程中会运行生命周期钩子函数

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • beforeDestroy
  • destroyed

模板语法

# 插值表达式

  • Mustanche语法{{msg}}
  • Mustanche标签将被替代和绑定为对应数据对象上的msg属性的值
  • {{}}中的Javascript表达式会在所属Vue实例的数据作用域下被解析
  • v-once元素下的的插值表达不会二次更新

# 指令

指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM

## 动态参数

2.6.0 新增

  • 动态属性:[attributeName]="value"
    • attributeName会被作为一个Javascript表达式进行动态求值,求得的值会作为最终的参数来使用
    • 如果Vue实例有一个data属性attributeName(值为href),和一个属性value(值为bing.com),那最终这个绑定将等价于 href="bing.com"
  • 动态事件@[eventName]="doSomething"
  • 对动态参数的值的约束
    • 预期:String
    • 异常:null,它可以显性地用于移除绑定
  • 对动态参数表达式的约束
    • 不要用大写(HTML大小写不第三)
    • 使用没有空格或引号的表达式
    • 复杂表达式用计算属性替代

计算属性和侦听器

# 计算属性

  • 作用:避免模板中放过多逻辑(防模板过重且难以维护)
  • 位置:位于实例的computed对象中
  • 计算属性的值是一个函数,这个函数将用作属性的getter函数
  • 与方法的不同:计算属性只会在第一次访问和当其中依赖值改变时调用函数 若在第一次访问之后再次访问,且其中依赖的数据没有变动时,是直接调取之前缓存的值

## 计算属性的setter

  • 计算属性默认只有getter,在需要时也可以提供一个setter
    // ...
    computed: {
      <计算属性> : {
        //getter
        get: function(){
          //...
        },
        //setter
        set: function(){
          //...
        }
      }
    }
    
    

# 侦听器

当需要在数据变化时执行异步或开销较大的操作时,采用自定义侦听器是最有用的

  • 作用:当侦听的数据变更时,调用方法
  • 位置:位于实例的watch对象中
    //...
    watch: {
      <data中的某一属性> : function(newValue, oldValue){
        //...
      }
    }
    

Class 与 Style 绑定

# 绑定 HTML Class

## 对象语法

通过给 v-bind:class 传递一个对象,可以动态的切换 class

  • :class="obj" 其中的 objdata 中的一个属性,其中 key 为 class 名, value 为 boolean 值(value为真时,对应的 class 将被渲染到元素中,否则不渲染)
  • :class="{ <className> : <boolean> }"<className>可以是data中的一个变量,也可以是字符字面量
  • :class="<计算属性>",其中的计算属性应返回一个对象

## 数组语法

数组中的 class ,都将被添加到元素中

  • :class = "[<className>, <className> ..."
  • :class = "[{<className> : <boolean>}, <className>]"

## 用在组件上

在一个自定义组件上使用 class 属性时,这些 class 将被追加到组件的根元素上

# 绑定内联样式

一般内联样式不用,所以这里就忽略吧,有需要再看


条件渲染

# v-if

  • 给一组元素添加 v-if 切换

    通过使用 <template> 包裹需要切换的元素,将 v-if 添加到它上面

  • key管理可利用的元素

    v-ifv-else 中的元素相同时,若其中有 <input> ,用户输入的内容不会被替换——仅仅替换它的 placeholder

    例如:

    <template v-if="loginType === 'username'">
      <label>Username</label>
      <input placeholder="Enter your username">
    </template>
    <template v-else>
      <label>Email</label>
      <input placeholder="Enter your email address">
    </template>
    

    当通过逻辑,切换 loginType 是否等于 username 时, <input> 中的用户输入不会被重制

    这在部分情况下是很 NICE 的,但是在这里明显不合逻辑,所以,通过为元素添加不同的 key 属性,以表示这两个元素是完全独立的,不要复用它们

# v-show

  • v-show 不支持 <template> 元素
  • v-show 的元素会始终被渲染并保留在 DOM 中
  • v-show 只是简单切换元素的 CSS 属性 display

# v-if vs v-show

  • v-if 是真正的条件渲染,它的改变会直接作用在 DOM 上
  • v-if 有更高的切换开销,v-show 有更高的初始渲染开销

# 不推荐在同一元素上同时使用 v-ifv-for


列表渲染

# 用 v-for 把一个数组对应为一组元素

  • 语法: v-for = "(item, index) in items"
    • items 是源数据数组
    • item 是被迭代的数组元素的别名
    • index 是当前项的索引 可省略
    • in 可以 换成 on

# 用 v-for 遍历对象中的属性

  • 语法:v-for = "(value, property, index) in object"
    • value 是对应当前 property 的值
    • property 是当前项的键名
    • index 当前索引 - 由于是按 Object.keys() 的结果遍历的,所以不同引擎下可能结果不一

# 维护状态

Vue 更新正在使用 v-for 渲染的元素列表时,它默认就地更新元素,不会移动 DOM 匹配数据荐的顺序

这并不适用于依赖子组件状态或临时 DOM 状态的列表渲染输出

为了 Vue 能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每期提供一个唯一的 key 属性

# 数据更新检测

## 变异方法

调用变异方法,会改变原始数组 Vue 将被侦听的数组的变异方法进行了包裹,所以它们也将触发视图更新

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

## 替换数组

调用非变异方法,会返回一个新数组,并不改变原始数组

  • filter()
  • concat()
  • slice()

## Vue 不能检测数组变动的情况

  • 利用索引直接设置一个数组项时: vm.items[index] = newValue
    • 解决方法1:使用 Vue.set(vm.items, index, newValue)
    • 解决方法2:使用 vmi.items.splice(index, 1, newValue)
  • 修改数组长度时: vm.items.length = newLength
    • 解决方法:使用 vm.items.splice(newLength)

# 对象变更检测注意事项

  • Vue 不能检测对象属性的添加或删除
  • 对于已创建的实例,Vue 不允许动态添加根级别的响应式属性,但是可以向嵌套对象添加响应式属性 Vue.set(object, propertyName, value)
    var vm = new Vue({
      data: {
        userProfile: {
          name: 'ankie'
        }
      }
    })
    Vue.set(vm.userProfile, 'age', 18)
    
  • 为已有对象赋值多个新属性
    vm.userProfile = Object.assign({}, vm.userProfile, {
      age: 27,
      favoriteColor: 'Vue Green'
    })
    

# 显示过滤/排序后的结果

  • 通过创建一个计算属性,来返回过滤或排序后的数组
    • v-for = "item in <计算属性>
  • 计算属性不适用的情况下,可以使用方法

# 在 v-for 里使用值范围

  • v-for = "n in 10
    • n 会被遍历 10 次, 值分别为 1 2 3 4 5 6 7 8 9 10

# 可以在 <template> 上使用 v-for

# v-forv-if 一同使用

不推荐在同一元素上同时使用 v-ifv-for

  • 同一元素:优先使用 v-forv-if 将分别重复运行于每个 v-for 循环中
  • 有目的地跳过循环的执行,将 v-if 置于外层元素或 <template>

# 在组件上使用 v-for

  • 任何数据都不会被自动传递到组件中(组件有自己独立的作用域)
  • 可以通过向组件已定义的 prop 对象中的属性传递数据,达到向组件传递数据

还未了解过的点

  • 虚拟DOM