*Vue.js 实战* 基础篇 学习笔记



书本信息:

 << Vue.js 实战 >> 作者: 梁灏

学习笔记 部分内容摘自书 非原创 侵删

第二章 数据绑定


2.1.4 过滤器

推荐用 computed 来实现
在 {{}} 插值尾部添加一个管道运行算符 | 对数据进行过滤

{{ data | formatDate }
  • 串联

{{ message | filterA | filterB }}

  • 接收参数

{{ message | filterA('arg1', 'arg2') }}


第三章 计算属性


3.2 计算属性用法

每一个计算属性都包含一个 gettter 和一个 setter, 在我们需要时, 可以提供一个 setter 函数, 当手动修改计算属性的值就行修改一个普通数据那样时, 就会触发 setter 函数, 执行一些自定义的函数

姓名: {{ fullName }}

当执行 app.fullName = 'John Doe'; 时, setter 就会被调用, 数据 firstName 和 'lastName' 都会相对更新, 视图也会更新.


第五章 内置指令


5.1.2 v-once

v-once 不需要表达式, 定义它的组件或组件只渲染一次, 包括元素或组件的所有子节点
首次渲染后, 不再岁数据的变化重新渲染, 将被视为静态内容
{{ message }}


5.2.1 key 属性 元素复用

Vue 在渲染元素时出于效率考虑, 会尽可能的复用已有元素而非重新渲染
如果你不希望这样, 可以使用 key 属性, 可以让你自己决定是否要复用元素, key 的值必须唯一


5.3 列表渲染 v-for

  • 数组

  • {{ index }} - {{ book.name }}
    • 对象

  • {{ index }} - {{ key }}: {{ value }}
    • 整数

    {{ n }}
    结果是 1 2 ...... 10


    5.3.2 数组更新

    Vue 的核心是数据与视图的双向绑定, 当我们修改数组时, Vue 会检测到数据变化, 所以用 v-for 渲染的也会立即更新. Vue 包含了一组观察数组变异的方法, 使用它们改变数组也会触发视图更新.

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

    使用以上方法会改变这些方法调用的原始数组, 有些方法不会改变原始数组

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

    它们返回的是一个新数组, 在使用这些非变异方法时, 可以用新数组来替换原始数组

    app.books = app.books.filter(function (item) {
        return item.name.match(/JavaScript/);
        // 对 books 数组做 filter 返回带有 JavaScript 的项
    })
    

    Vue 在检测到数组变化时, 并不是直接重新渲染整个列表, 而是最大化地复用 DOM 元素, 替换的数组中, 含有相同元素的项不会被重新渲染, 因此可以大胆地用新数组来替换旧数组, 不用担心性能问题.

    需要注意的是, 以下变动的数组中, Vue 是不能检测到的, 也不会触发视图更新

    • 通过索引直接设置项, 比如 `app.books[3] = {...}
    • 修改数组长度, 比如 `app.books.length = 1

    解决第一个问题可以用两种方法

    • set 方法
    Vue.set(app.books, 3, {
        name: 'changedName'
    });
    
    // webpack app.&set
    this.&set(app.books, 3, {
        name: 'changedName'
    })
    
    • 用 splice
    app.books.splice(3, 1, {
        name: 'changedName'
    })
    

    第二个问题也可以直接用 splice 来解决
    app.books.splice(1);


    5.4.2 修饰符

    在@绑定的事件后加小圆点 ".", 再更一个后缀来使用修饰符

    • .stop
    • .prevent
    • .capture
    • .self
    • .once

    具体用法

    // 阻止单击事件冒泡

    // 提交事件不再重载页面


    // 修饰符可以串联

    // 只有修饰符

    // 添加事件侦听器时使用事件捕获模式

    // 只当事件在该元素本身(而不是子元素)触发时触发回调

    // 只触发一次, 组件同样适用

    在表单元素上监听键盘事件时, 还可以使用按键修饰符, 比如按下某个键时猜调用方法

    // 只有在 keyCode 是13时代用 submit()

    也可以自己配置具体按键

    Vue.config.keyCodes.f1 = 112;
    // 全局定义后, 就可以使用 @keyup.f1

    除了具体的某个 keyCode, 还提供了一些快捷名称

    • .enter
    • .tab
    • .delete (删除和退格)
    • .esc
    • .space
    • .up
    • .down
    • .left
    • .right

    这些按键修饰符也可以组合使用, 或者和鼠标一起配合使用

    • .ctrl
    • .alt
    • .shift
    • .meta ( Mac 下是 Command, Windows 下是窗口键)

    第六章 表单与 v-model


    6.3 修饰符

    .lazy: 懒加载

    在输入框中, v-model 默认实在 input 事件中同步输入框的数据 (除了中文输入法输入的时候), 使用修饰符 .lazy 会转变为在 change 事件中同步

    .number: 将输入的 String 转换为 Number

    使用 .number 可以将输入转换为 Number 类型, 否则虽然你输入的是数字, 但是它的类型其实是 String, 在输入输入框中比较有用

    .trim: 自动过滤输入的首尾空格


    第七章 组件详解


    7.1.2 is 属性挂载组件

    Vue 组件的模板在某些情况下会受到 HTML 的限制, 比如

    内规定只允许是 ,
    , 等这些表格元素, 所以直接在 内使用组件是无效的, 这种情况下, 可以使用特殊的 is 属性来挂载组件
    常见的限制元素还有
      ,
        ,

    7.2.3 数据验证 props

    在组件中, 使用选项 props 来声明需要从父级接收的数据, props 的值可以是两种, 一种是字符串数组, 一种是对象
    当 prop 需要验证时, 就需要对象写法
    一般当你的组件需要提供给别人使用时, 推荐都进行数据验证, 比如某个数据必须是数字类, 如果是 string 就会在控制台弹出警告

    props: {
        // 必须是数字类型
        propA: Number,
        // 必须是字符串或者数字
        propB: [String, Number],
        // 布尔值, 如果没有定义, 默认为 true
        propC: {
            type: Boolean,
            default: true
        },
        // 数字, 而且是必传
        propD: {
            type: Number,
            required: true
        },
        // 如果是数组或者对象, 默认值必须是一个函数来返回
        propE: {
            type: Array,
            default: function () {
                return [];
            }
        },
        // 自定义验证函数
        propF: {
            validator: function (value) {
                return value > 10;
            } 
        }
    }
    

    验证的 type 类型可以是:

    • String
    • Number
    • Boolean
    • Object
    • Array
    • Function

    type 也可以是一个自定义构造器, 使用 instanceof 检测
    当 prop 验证失败时, 在开发版本下会在控制台抛出一条警告


    7.3.1 自定义事件 v-on .native 监听原生事件, 监听的是该组件的根元素

    当给一个 Vue 组件绑定事件的时候需要加上 .native
    否则 Vue 会认为这个是一个自定义事件 v-on 来监听子组件的 $emit()


    7..3.2 自定义组件使用 v-model

    
    ...
    methods: {
        handleClick () {
            this.counter++;
            this.$emit('input', this.counter);
        }
    }
    

    组件 $emit() 的事件名是特殊的 input, 在使用组件的父级, 并没有在 上使用 @input="handler", 而是直接使用了 v-model 绑定的一个数据 total, 也可以用自定义事件实现

    
    ...
    methods: {
        handleGetTotal (total) {
            this.total = total;
        }
    }
    

    v-model 还可以用来创建自定义的表单输入组件, 进行数据双向绑定

    
    
    ...
    
    ...
    methods: {
        updateValue (event) {
            this.$emit('input', event.target.value);
        }
    }
    

    实现这样一个具有双向绑定的 v-model 组件需要满足下面两个要求

    • 接收一个 value 属性
    • 在有新的 vaue 时触发 input 事件

    7.3.3 非父子组件通信

    组件通信几种方式

    • $emit() $on() 只能父子组件通信, 子组件 props 接收父组件数据
    • bus 空 Vue 实例
    • vuex
    • 父链和子组件索引

    父链

    在子组件中, 使用 this.$parent 可以直接访问该组件的父实例或组件, 父组件也可以通过 this.$children 访问他所有的子组件, 而且可以递归向上或者向下无限访问, 一直到根实例或最内层的组件

    子组件索引

    当子组件较多时, 通过 this.$children 来一一遍历出我们需要的一个组件实例是比较困难的, 尤其是当组件动态渲染时, 他们的序列不是固定的. Vue 可以使用特殊的属性 ref 来为子组件指定一个索引名称

    ... methods: { handleRef () { var msg = this.$refs.comA.message; console.log(msg); } }

    在父组件模板中, 子组件标签上使用 ref 指定一个名称, 并在父组件内通过 this.$refs 来访问指定名称的子组件

    注意: $refs 只在组件渲染完成后才填充, 并且他是非响应式的, 它仅仅作为一个直接访问子组件的应急方案, 应当避免在模板或计算属性中使用


    7.4.4 作用域插槽

    作用域插槽是一种特殊的 slot, 使用一个可以复用的模板替换已渲染元素

    // 列表组件, 允许组件自定义应该如何渲染列表每一项
    
    // 作用域插槽也可以是具名的 slot

    父组件当中 scope="props", 这里的 props 只是一个临时变量, 就像 v-for="item in items" 里面的 item 一样. template 可以通过临时变量 props 访问来自子组件插槽的数据

    在这个例子当中, 子组件 my-list 接收父级的 prop 数组 books, 并且将它在 name 为 book 的 slot 上使用 v-for, 同时暴露一个变量 bookName

    这个作用域插槽的使用场景就是即可以复用子组件的slot, 又可以使 slot 内容不一致. 如果上例还在其他组件内使用,

  • 的内容渲染权是由使用者掌握的, 而数据却可以通过临时变量 (比如 props) 从子组件内获取


    7.4.5 访问 slot

    this.$slots.name

    this.$slots.default     //包括了所有没有被包含在具名 slot 中的节点


    7.5.3 动态组件

    Vue 提供了一个特殊元素 来动态地挂载不同的组件, 使用 is 特性来选择要挂载的组件


    7.6.1 $nextTick

    Vue 中异步更新队列

    Vue在观察到数据变化时并不是直接更新 DOM, 而是开启一个队列, 并缓冲在同一事件循环中发生的所有数据改变. 在缓冲时会去除重复数据, 从而避免不必要的计算和 DOM 操作.

    然后, 在下一个事件循环 tick 中, Vue 刷新队列并执行实际 (已去重) 工作. 所以如果你用一个 for 循环来动态改变数据100次, 其实它只会应用最后一次改变, 如果没有这种机制, DOM 就要重绘100次, 这显然是一个很大的开销.
    Vue 会根据当前浏览器环境优先使用原生的 Promise.then 和 MutationObserver, 如果都不支持, 就会采用 setTimeout 代替.
    知道了 Vue 异步更新 DOM 的原理, 上面示例的报错也就不难理解了. 事实上, 在执行 this.showDiv=true; 时, div 仍然还是没有被创建出来, 直到下一个 Vue 事件循环时, 才开始创建. $nextTick 就是用来知道什么时候 DOM 更新完成的

    这是一段文本

    这时候点击按钮, 控制台会打印出 div 的内容 "这是一段文本"

    理论上, 我们应该不用主动操作DOM, 因为 Vue 的核心思想就是数据驱动 DOM, 但在很多业务里, 我们避免不了会使用一些第三方库, 比如 popper.js, swiper 等, 这些基于原生 js 的库都有创建和更新及销毁的哇证生命周期, 与 Vue 配合使用时, 就要利用好 $nextTick

    vue nextTick深入理解-vue性能优化、DOM更新时机、事件循环机制


    7.6.3 手动挂载实例

    动态地创建 Vue 实例, Vue 提供了 Vue.extend 和 $mount 两个方法来手动挂载一个实例.

    Vue.extend 是基础 Vue 构造器, 创建一个 子类 , 参数是一个包含组件选项的对象.

    如果 Vue 实例在实例化时没有收到 el 选项, 它就处在 '未挂载' 状态, 没有关联的 DOM 元素. 可以使用 $mount() 手动地挂载一个未挂载的实例. 这个方法返回实例自身, 因而可以链式调用其他实例方法.

    除了这种写法外, 以下两种写法也是可以的

    new MyComponent().$mount('#mount-div');
    // 同上
    new MyComponent({
        el: '#mount-div'
    });
    // 或者, 在文档之外渲染并且随后挂载
    var component = new MyComponent().$mount();
    document.getElementById('mount-div').appendChild(component.$el);
    

    手动挂载实例 (组件) 是一种比较极端的高级用法, 在业务中几乎用不到, 只在开发一些复杂的独立组件时可能会使用, 这边只做了解.

    Vue2 几种常见开局方式


    第八章 自定义指令


    8.1 基本用法

    exp. 注册一个 v-focus 的指令, 用于在 ,