[关闭]
@delight 2017-02-27T08:00:55.000000Z 字数 4318 阅读 1868

Vue.js核心要点

js 前端


新的项目决定使用Vue2.0配合Element UI框架来写,不再使用老一套的Backbone了,也算是一种学习吧。

集大成者

Vue是一个年轻的框架,同时有Angular的设计风格和React的Virtual DOM速度优势。

模板式语法

仍然保留了模板式语法,{{}}来解释变量/表达式

指令

类似Angular的一套指令,以v-开头,常用的包括:
1. v-bind,变量绑定,v-bind:title="title",绑定元素的title属性为title变量,可以缩写为:,即省略v-bind仅保留冒号;
2. v-if,条件判断,对应的也有v-elsev-else-if
3. v-for,循环,格式为v-for="x in xs",也可以使用es6的of语法;在同一个节点上同时使用v-forv-if时,前者具有更高的优先级。这意味着v-if将分别在循环的每次迭代上运行;
4. v-on,事件绑定,如v-on:click="func",值是回调函数的名字,可以缩写为@。回调函数被定义在app的methods属性中;
5. 可以加入修饰符完成常用动作,如v-on:click.prevent,相当于加入了preventDefault()。常见修饰符包括:.stop, .prevent,.capture, .self.once。另外还有一些按键修复符,用来绑定keyup等键盘事件,如keyup.delete
6. 有时也需要在内联语句处理器中访问原生 DOM事件。可以用特殊变量 $event 把它传入方法;
7. v-model,变量的双向绑定,如一个inputv-model="title的属性,那么title就和这个变量相互映射;可以结合v-bind使用;
8. v-once仅仅进行一次性插值,不再根据model进行更新;

特殊绑定

对于HTML的class和style,拼接字符串较为麻烦。这里进行了一些增强。

对于class可以直接传入一个对象,如:

  1. data: {
  2. classObject: {
  3. active: true,
  4. 'text-danger': false
  5. }
  6. }

那么

  1. <div v-bind:class="classObject"></div>

将被渲染为:

  1. <div class="static active"></div>

另外,也可以直接绑定为一个计算属性,或者一个数组列表。或者可以用:

  1. <div v-bind:class="[{ active: isActive }, errorClass]">

这种格式,直接嵌入列表或对象。

style与之类似,可以直接传入css的各种属性,以列表/对象的形式。

key

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有唯一 id。

过滤器

也是比较常见的模板系统组件,使用管道操作符,连接一些过滤器对数据进行简单的变换。过滤器可以定义在app的filters里面,是一个单字符串参数的函数

计算属性

不宜在模板中使用过重的逻辑,如果有需要,使用计算属性。可以在app的computed属性中设置一系列的函数,然后像普通属性一样在模板中进行引用。注意计算属性和普通函数的区别是后者每次都会进行重新计算,但是前者是有缓存的,如果使用的普通属性不变,不会进行重新计算;

默认情况下计算属性对应的函数即是这个属性的getter,如果有需要的话可以显式写成:

  1. {
  2. attr: {
  3. get: function(){},
  4. set: function(newvalue){},
  5. }
  6. }

的形式。

观察器

可以在app中定义watch属性,监视某些属性的变化,并执行一些复杂的逻辑或者异步操作。

数组变异

渲染数组元素到具体的页面元素时,然后数组本身发生了变化,页面会被重新渲染。但是并非所有的数组变化都能被正确检测到,需要注意的包括:

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

以上两个行为可以使用以下方法代替:

  1. Vue.set(example1.items, indexOfItem, newValue)
  2. example1.items.splice(newLength)

组件系统

将图形界面就行抽象,分离成各个组件,这就是web component. 这不是什么新的概念。然后Vue的组件其实和React的有点像,最后生成的样子也是一层套一层的组件。形如:

  1. <div id="app"> <!--最外层的APP,根元素-->
  2. <app-nav></app-nav> <!--导航栏-->
  3. <app-view> //主视图
  4. <app-sidebar></app-sidebar> <!--边栏-->
  5. <app-content></app-content> <!--应用的内容区-->
  6. </app-view>
  7. </div>

应用

每个app通过new Vue({})来生成实例,也可以通过extend对该类进行扩展。

每个Vue实例都会代理其data属性中的所有字段,但是要注意的是,只有在data中声明的变量才是动态响应的,后来注入的不行。

该实例还暴露了一些方法和属性,为了区别与data中的属性,这些属性都以$开头,所以$el就是实例绑定的元素(和Backbone一样)。

应用在不同生命周期内定义了一些回调函数,如mounted, updateddestroyed等等,详细如下图(来自官网):

Vue应用的生命周期图

组件

使用Vue.component来注册全局组件,要在初始化根实例之前注册全局组件。对于局部组件,可以在app内部使用components属性注册。

DOM模板在使用组建时有些限制,嵌套式元素如select, table, ul, ol, 其内部元素是规定死的,例如select下面只有option,用自己注册的my-option是不会被解析的,可以使用is属性来变通<option is="my-option">

但是使用其他模板,如<script type="text/x-template">,js内联的模板d或者.vue后缀的组件时,均不受上面的限制。

组件的data属性必须是一个函数。

组件的嵌套关系:父组件通过props向子组件传递数据,子组件通过events向父组件发送消息。子组件使用props属性显式声明需要传递的属性。

prop

在DOM模板中,由于HTML本身不区分大小写,这些prop在从父组件传递过来的时候需要转化为kebab-case形式(即使用短横线隔开)。

子组件可以使用v-bind绑定prop,这样父组件的数据变化会传递给子组件。

不要使用字面量传递数值,使用v-bind.

prop是单向数据流,从父组件传递给子组件,子组件不应该改变这些传递过来的数据(const),如果有需要的话,可以定义一个局部变量或者计算属性。

可以为prop定义验证,确定一种模型规约。

events

父组件可以在使用子组件的地方用v-on监听子组件触发的事件;
子组件使用$emit触发事件;
如果想要监听原生事件,可以使用.native修饰器;

如果想使用v-model,需要在组件里面处理v-on:input事件,最后$emit出iinput事件给父组件,还有一个处理后的值。

有时候非父子组件也需要通信,可以考虑创建一个空的Vue实例作为中央事件总线,或者使用状态管理组件(vuex).

slot

slot是一套约定,解决的是父组件和子组件如何组合模板的问题。

首先考虑编译作用域的问题,父组件不应该知道子组件的状态,因此父组件在使用子组件的时候也不应该直接引用子组件的属性。

如果子组件没有<slot>标签,那么父组件中的所有模板都会被丢弃。如果有,用父组件的内容替换掉slot中的内容。

slot可以有一个name属性,具名后的版本与父组件模板中的元素slot熟悉感的名字一一对应,如果找不到对应的名字,使用匿名的默认slot.

有一种特殊的插槽名为作用域插槽,子组件可以将数据传递到插槽,父组件通过template元素的scope属性接受该属性,这相当于从子组件到父组件传递数据。

动态组件

多个组件可以使用同一个挂载点,使用特殊的<component v-bind:is="viewName">来加载组件。如果想要避免重新渲染,可以在外围加上<keep-alive>标签。

ref

有时候需要在js中直接通过父组件访问子组件(一般是设计问题,考虑重构),可为子组件指定一个ref,然后在通过parent.$refs.refName访问

异步支持

可以将组件注册为一个异步组件,例如配合webpack后可以:

  1. Vue.component(
  2. 'async-webpack-example`,
  3. () => import('./my-async-component')
  4. )

命名约定

习惯上使用kebab-case命名组件,因为HTML模板中必须使用该格式。但是如果使用其他模板,就无所谓了,可以按着js的命名原则写。

递归引用

允许组件递归调用自己,前提是有一个name选项。

循环引用

异步加载的时候可能会遇到循环引用的问题,需要使用beforeCreate钩子提前注册引用的组件。

v-once

对于大量静态内容的组件,可以考虑使用v-once进行缓存。

过渡效果

vue提供了transition封装组件,可以给任何元素或组件添加entering/leaving过渡,只需在css中定义好对应名称的过渡/动画。

动画这一块的细节较多,暂时略过(对控制台来说不太重要

render函数

大部分时候我们使用template完成HTML的创建,但是有时候可能直接写模板代码过于冗长反复,这时候可以用render函数来替代,使用createElement函数创建HTML元素。

或者可以选择使用jsx语法,利用babel一个插件,使得vue支持jsx

自定义指令

显然组件化是主要的写法,但是有时候可能需要对纯DOM进行操作,这时候就要用到自定义指令。

全局指令通过Vue.directive('name',{event: function})来注册,其中event是钩子事件。

单文件组件

使用.vue格式的文件来完成单文件组件。配合webpack和babel来书写es2015的代码。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注