前端Vue专辑Web前端之路程序员

Vue的特性精华

2017-07-28  本文已影响2372人  科研者

以下内容是我在学习和研究Vue时,对Vue的特性、重点和注意事项的提取、精练和总结,可以做为Vue特性的字典;

1. 性能优化:

2. v-if和v-show

v-if支持v-else和v-else-if语法,也支持< template>语法;v-show不支持这些;
v-show是通过简单地切换元素的CSS属性display属性来实现显示隐藏效果;
v-if 是“真正的”条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块;
相比之下, v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换;
也可以使用key标签属性来实现元素的切换显示;

3. 支持< template>的指令

v-if、v-else、v-else-if、v-for,等结构性指令;

4. 模板语法

  1. 双大括号{{表达式}}语法会将表达式的值作为纯文本,而非 HTML;若要输出真正的 HTML ,需要使用 v-html 指令;
  2. 双大括号{{表达式}}语法不能作用在 标签属性上;若要作用在标签属性上,应该使用 v-bind 指令;
  3. 插值模板表达式只能是单个表达式;
  4. 插值表达式是被放在沙盒中执行的,只能访问全局变量的一个白名单,如 Math 和 Date 。不应该在模板表达式中试图访问用户定义的全局变量;

5. 组件

  1. Vue.component的主要功能是注册组件,不是创建组件;
  2. 所有的 Vue.js 组件其实都是被扩展的 Vue 实例;
  3. 使用Vue.component注册组件时,创建Vue实例的代码必须在注册组件的代码的后面,否则注册的组件不会被显示;
  4. Vue.component(id,[definition])的参数id是字符串类型,它用于定义组件的标签名,所以不能通过传入id选择器、类选择器、属性选择器等等来定义组件;

6. Vue特性

  1. 当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。

  2. 事件可以以链式的方式添加多个事件修饰符,修饰符会按照修饰的顺序起作用;

  3. 在vue中,双大括号{{}}语法不能用在标签属性中;

  4. 在textarea标签中使用双大括号{{}}语法并不会生效,应用v-model来实事插值;

  5. 在Vue中,对于所有的数据绑定,都支持JavaScripot表达式,这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式;

  6. 当使用DOM 作为模版时 (例如,将 el 选项挂载到一个已存在的元素上), 会受到 HTML 的一些限制,因为 Vue 只有在浏览器解析和标准化 HTML 后才能获取模版内容,所以,如果DOM模版中包含了一些非法的标签,则将会被浏览器移除掉;

  7. 如果需要在某个组件的根元素上监听一个原生事件,可以使用 .native 修饰 v-on绑定的事件;

  8. 只能在字符串模板中使用自动闭合的组件名标签,因为对浏览器来说,自动闭合的自定义元素是无效的HTML标签;

  9. Vue 不允许在已经创建的实例上动态添加新的根级响应式属性(root-level reactive property);

  10. 当你设置 vm.someData = 'new value' ,该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新;

  11. 如果同时设置了transitionend 和animationend ,则需要使用transition标签的 type 标签属性并设置 animation 或 transition 来明确声明你需要 Vue 监听的类型;

  12. 使用 FLIP 过渡的元素不能设置为 display: inline 。作为替代方案,可以设置为 display: inline-block 或者放置于 flex 中;

  13. 当 v-bind:style 使用需要特定前缀的 CSS 属性时,如 transform,Vue.js 会自动侦测并添加相应的前缀;

7. 当创建组件时,data选项应是是函数类型的原因

选项data可以是Object类型,也可以是Function类型,当data是Function类型时,data函数必须返回一个Object实例作为真正的data选项的值;
但在定义组件时,选项data最好应该是函数类型,因为,如果data是对象类型,则当此组件需要被用来创建多个实例时,则所有的实例将都引用同一个data实例;然而,如果将data定义为函数类型,并在函数里面返回新创建的对象,则每当此组件创建实例时,就会引用 data函数返回的全新的对象,从而不会使此组件的实例共享同一个data对象;

8. 指令

指令(Directives)是带有 v- 前缀的特殊标签属性。指令属性的值预期是单一 JavaScript 表达式(除了 v-for)。指令的职责就是当其表达式的值改变时相应地将某些行为应用到 DOM 上。

9. 过滤器

Vue允许你自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:{{}} 插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由管道符|指示开始位置;

10. 选项:template

11. 选项:data

12. 选项:computed

13. 选项:watch

14. 标签属性key的理解

Vue 为了尽可能高效地渲染元素,通常会复用已有元素而不是重新创建元素;为了不让vue复用已有的元素,可以给元素加个标签属性key,并给该标签属性赋一个字符串类型的值;我认为这个标签属性key可以理解为IOS中的重用标识符;

15. 数组

由于 JavaScript 的限制, Vue 不能检测以下变动的数组:

  1. 当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength

为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果, 同时也将触发状态更新:
方法1:

// Vue.set
Vue.set(example1.items, indexOfItem, newValue)

方法2:

// Array.prototype.splice
example1.items.splice(indexOfItem, 1, newValue)

为了解决第二类问题,可以使用splice

example1.items.splice(newLength)

16. 对象更改检测注意事项

  1. 由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除;
  2. 对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, key, value) 方法向嵌套对象添加响应式属性;

17. 事件

所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的ViewModel上;当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除;
可以通过Vue.config.keyCodes对象自定义键值修饰符别名,格式如下:

// 可以使用 v-on:keyup.f1
Vue.config.keyCodes.f1 = 112

或者:

Vue.config.keyCodes = {
  v: 86,
  f1: 112,
  // camelCase 不可用
  mediaPlayPause: 179,
  // 取而代之的是 kebab-case 且用双引号括起来
  "media-play-pause": 179,
  up: [38, 87]
}

18. 双向绑定v-model指令

  1. v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值。因为它会选择 Vue 实例数据来作为具体的值。所以应该通过 JavaScript 在组件的 data 选项中声明初始值。
  2. 当在select元素中使用v-model时,如果 v-model 表达初始的值不匹配任何的选项,select 元素就会以”未选中”的状态渲染。

19. props

  1. 在使用组件时,若需要通过标签属性给子组件传数据,则需要先显式地在 props 选项声明;
  2. prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
  3. 在JavaScript 中对象是引用类型,如果 prop 是一个对象,在子组件内部改变它的属性值会影响父组件的状态;
  4. props 会在组件实例创建之前进行校验,所以在 default 或 validator 函数里,诸如 data、computed 或 methods 等实例属性还无法使用。

20. Vue中实现双向绑定的指令

Vue中实现双向绑定的所有方式都是一个语法糖,本质都是通过v-bind指令 和 v-on指令实现的;
它们的具体实现方式如下:

  1. 修饰符.sync
    示例:

    < comp v-bind:foo.sync="bar"></comp>
    

    等效语法:

    < comp :foo="bar" @update:foo="val => bar = val"></comp>
    

    当子组件需要更新 foo 的值时,它需要显式地触发一个更新事件:

    this.$emit('update:foo', newValue)
    
  2. 指令v-model

    1. v-model用于原生input元素时,有如下等效:
      示例:
    < input v-model="something">
    

    等效语法:

    < input
      v-bind:value="something"
      v-on:input="something = $event.target.value">
    
    1. v-model用于自定义组件时,有如下等效:
      示例:
    < my-component v-model="something">
    

    等效语法:

    < my-component
      v-bind:value="something"
      v-on:input="something = arguments[0]">< /my-component>
    

    所以,如果要在组件上使用v-model,则组件应该具备以下条件:

    1. 有一个名字是value的prop;
    2. 当需要向父组件更新新值时,需要通过触发名字为input的事件传值;
    1. 更改组件中v-model默认绑定的prop和事件
      默认情况下,一个组件的 v-model 会使用 value 属性和 input 事件,不过,可以通过选项model更改v-model默认绑定的prop和事件;
      示例如下:
    Vue.my-component('my-component', {
      props: {
        checked: Boolean
      },
      model: {
        prop: 'checked',
        event: 'change'
      }
    })
    

    然后,可以如下使用v-model:

    < my-component v-model="foo" value="some value">< /my-component>
    

    等效语法:

    < my-component
      :checked="foo"
      @change="val => { foo = val }">< /my-component>
    

21. 内容分发

  1. 如果组件模板中没有包含slot插口,则在使用组件时,组件标签内的内容将被丢弃;
  2. 如果组件模板只有一个没有属性的slot,则在使用组件时,组件标签内的内容都将插入slot所在的DOM位置,并替换掉slot标签本身;
  3. 组件模版中slot标签中的任何内容都被视为备用内容;备用内容在子组件的作用域内编译;并有只有没有要插入的内容时,才会显示备用内容;
  4. 可以通过配置slot的name标签属性来分发内容;仍然可以有一个匿名 slot,它是默认 slot,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot,这些找不到匹配的内容片段将被抛弃;

22. 作用域插槽

作用域插槽是一种特殊类型的插槽,用作使用一个 (能够传递数据到) 可重用模板替换已渲染元素;
使用方式如下:
在组件模板中给slot标签设置的标签属性,可以在使用组件时,通过该组件标签内部的template元素的scope标签属性访问;
具体示例如下:
子组件的模板:

< div class="child">
  < slot text="hello from child">< /slot>
< /div>

使用子组件:

< div class="parent">
  < child>
      < template scope="props">
          < span>hello from parent< /span>
      < span>{{ props.text }}< /span>
      < /template>
    < /child>
< /div>

标签属性scope是被用来定义临时变量的,被定义的临时变量就是scope的值,也就是说:此例中的props是被定义临时变量;这个临时变量保存的是从子组件中传递出来的props对象;
如果我们渲染以上结果,得到的输出会是:

< div class="parent">
  < div class="child">
      < span>hello from parent< /span>
      < span>hello from child< /span>
  < /div>
< /div>

注意:

23. 动态定义组件的模板的方式

  1. 内容分发:用slot标签;
  2. 作用域插槽:用template和slot标签;
  3. 动态组件:用预定义的component标签;
  4. 内联模版:用标签属性inline-template;
  5. 路由;

24. 路由

  1. 同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高;

25. 子组件实例的引用

通过如下方式,可以在JavaScript中获取子组件实例的引用:

  1. 在子组件上设置 ref 标签属性;

    <child-component ref="引用名字" >
    
  2. 通过当前组件实例的 $refs 属性 当前组件实例.$refs.引用名字 获取子组件实例的引用,如:

    this.$refs.引用名字
    

注意:

26. 内联模板

如果子组件有 inline-template 特性,组件将把它的内容当作它的模板,而不是把它当作分发内容。这让模板编写起来更灵活。

<my-component inline-template>
  <div>
    <p>这些将作为组件自身的模板。</p>
    <p>而非父组件透传进来的内容。</p>
  </div>
</my-component>

但是 inline-template 让模板的作用域难以理解。使用 template 选项在组件内定义模板或者在 .vue 文件中使用 template 元素才是最佳实践。

27. X-Template

另一种定义模板的方式是在 JavaScript 标签里使用 text/x-template 类型,并且指定一个 id。例如:

<script type="text/x-template" id="hello-world-template">
  <p>Hello hello hello</p>
</script>
Vue.component('hello-world', {
  template: '#hello-world-template'
})

这在有很多大模板的演示应用或者特别小的应用中可能有用,其它场合应该避免使用,因为这将模板和组件的其它定义分离了。

上一篇下一篇

猜你喜欢

热点阅读