@delight
2017-02-27T08:00:55.000000Z
字数 4318
阅读 2208
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-else和v-else-if;
3. v-for,循环,格式为v-for="x in xs",也可以使用es6的of语法;在同一个节点上同时使用v-for和v-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,变量的双向绑定,如一个input有v-model="title的属性,那么title就和这个变量相互映射;可以结合v-bind使用;
8. v-once仅仅进行一次性插值,不再根据model进行更新;
对于HTML的class和style,拼接字符串较为麻烦。这里进行了一些增强。
对于class可以直接传入一个对象,如:
data: {classObject: {active: true,'text-danger': false}}
那么
<div v-bind:class="classObject"></div>
将被渲染为:
<div class="static active"></div>
另外,也可以直接绑定为一个计算属性,或者一个数组列表。或者可以用:
<div v-bind:class="[{ active: isActive }, errorClass]">
这种格式,直接嵌入列表或对象。
style与之类似,可以直接传入css的各种属性,以列表/对象的形式。
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有唯一 id。
也是比较常见的模板系统组件,使用管道操作符,连接一些过滤器对数据进行简单的变换。过滤器可以定义在app的filters里面,是一个单字符串参数的函数
不宜在模板中使用过重的逻辑,如果有需要,使用计算属性。可以在app的computed属性中设置一系列的函数,然后像普通属性一样在模板中进行引用。注意计算属性和普通函数的区别是后者每次都会进行重新计算,但是前者是有缓存的,如果使用的普通属性不变,不会进行重新计算;
默认情况下计算属性对应的函数即是这个属性的getter,如果有需要的话可以显式写成:
{attr: {get: function(){},set: function(newvalue){},}}
的形式。
可以在app中定义watch属性,监视某些属性的变化,并执行一些复杂的逻辑或者异步操作。
渲染数组元素到具体的页面元素时,然后数组本身发生了变化,页面会被重新渲染。但是并非所有的数组变化都能被正确检测到,需要注意的包括:
vm.items[indexOfItem] = newValuevm.items.length = newLength以上两个行为可以使用以下方法代替:
Vue.set(example1.items, indexOfItem, newValue)example1.items.splice(newLength)将图形界面就行抽象,分离成各个组件,这就是web component. 这不是什么新的概念。然后Vue的组件其实和React的有点像,最后生成的样子也是一层套一层的组件。形如:
<div id="app"> <!--最外层的APP,根元素--><app-nav></app-nav> <!--导航栏--><app-view> //主视图<app-sidebar></app-sidebar> <!--边栏--><app-content></app-content> <!--应用的内容区--></app-view></div>
每个app通过new Vue({})来生成实例,也可以通过extend对该类进行扩展。
每个Vue实例都会代理其data属性中的所有字段,但是要注意的是,只有在data中声明的变量才是动态响应的,后来注入的不行。
该实例还暴露了一些方法和属性,为了区别与data中的属性,这些属性都以$开头,所以$el就是实例绑定的元素(和Backbone一样)。
应用在不同生命周期内定义了一些回调函数,如mounted, updated和destroyed等等,详细如下图(来自官网):

使用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属性显式声明需要传递的属性。
在DOM模板中,由于HTML本身不区分大小写,这些prop在从父组件传递过来的时候需要转化为kebab-case形式(即使用短横线隔开)。
子组件可以使用v-bind绑定prop,这样父组件的数据变化会传递给子组件。
不要使用字面量传递数值,使用v-bind.
prop是单向数据流,从父组件传递给子组件,子组件不应该改变这些传递过来的数据(const),如果有需要的话,可以定义一个局部变量或者计算属性。
可以为prop定义验证,确定一种模型规约。
父组件可以在使用子组件的地方用v-on监听子组件触发的事件;
子组件使用$emit触发事件;
如果想要监听原生事件,可以使用.native修饰器;
如果想使用v-model,需要在组件里面处理v-on:input事件,最后$emit出iinput事件给父组件,还有一个处理后的值。
有时候非父子组件也需要通信,可以考虑创建一个空的Vue实例作为中央事件总线,或者使用状态管理组件(vuex).
slot是一套约定,解决的是父组件和子组件如何组合模板的问题。
首先考虑编译作用域的问题,父组件不应该知道子组件的状态,因此父组件在使用子组件的时候也不应该直接引用子组件的属性。
如果子组件没有<slot>标签,那么父组件中的所有模板都会被丢弃。如果有,用父组件的内容替换掉slot中的内容。
slot可以有一个name属性,具名后的版本与父组件模板中的元素slot熟悉感的名字一一对应,如果找不到对应的名字,使用匿名的默认slot.
有一种特殊的插槽名为作用域插槽,子组件可以将数据传递到插槽,父组件通过template元素的scope属性接受该属性,这相当于从子组件到父组件传递数据。
多个组件可以使用同一个挂载点,使用特殊的<component v-bind:is="viewName">来加载组件。如果想要避免重新渲染,可以在外围加上<keep-alive>标签。
有时候需要在js中直接通过父组件访问子组件(一般是设计问题,考虑重构),可为子组件指定一个ref,然后在通过parent.$refs.refName访问
可以将组件注册为一个异步组件,例如配合webpack后可以:
Vue.component('async-webpack-example`,() => import('./my-async-component'))
习惯上使用kebab-case命名组件,因为HTML模板中必须使用该格式。但是如果使用其他模板,就无所谓了,可以按着js的命名原则写。
允许组件递归调用自己,前提是有一个name选项。
异步加载的时候可能会遇到循环引用的问题,需要使用beforeCreate钩子提前注册引用的组件。
对于大量静态内容的组件,可以考虑使用v-once进行缓存。
vue提供了transition封装组件,可以给任何元素或组件添加entering/leaving过渡,只需在css中定义好对应名称的过渡/动画。
动画这一块的细节较多,暂时略过(对控制台来说不太重要
大部分时候我们使用template完成HTML的创建,但是有时候可能直接写模板代码过于冗长反复,这时候可以用render函数来替代,使用createElement函数创建HTML元素。
或者可以选择使用jsx语法,利用babel一个插件,使得vue支持jsx
显然组件化是主要的写法,但是有时候可能需要对纯DOM进行操作,这时候就要用到自定义指令。
全局指令通过Vue.directive('name',{event: function})来注册,其中event是钩子事件。
使用.vue格式的文件来完成单文件组件。配合webpack和babel来书写es2015的代码。