@delight
2017-02-27T16:00:55.000000Z
字数 4318
阅读 2006
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] = newValue
vm.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的代码。