Comparison Between Vue 1 and Vue
模板语法
插值
- Vue 2 提供了
v-once
指令进行一次插值,替代了 Vue 1 的{{ * msg }}
。 - Vue 2 提供了
v-html
插入纯 HTML 文本,替代了 Vue 1 的{{{ rawHTML }}}�
。 - Vue 2 取消了在元素属性中直接使用 Mustache 语法的做法,所有的元素属性都要用
v-bind
进行绑定。 - Vue 2 为模板表达式添加了白名单,在模板中只能访问白名单内的全局变量。
过滤器
- 在 Vue 2 中,过滤器只能在 mustache 绑定和
v-bind
表达式中使用,对于更复杂的数据变换应当使用计算属性。
Class 与 Style 绑定
绑定 HTML Class
- Vue 2 允许
v-bind:class
与普通的 class 属性共存。 - Vue 2 中,在一个定制的组件上用到
class
属性的时候,这些类将被添加到根元素上面,这个元素上已经存在的类不会被覆盖。
条件渲染
v-if
-
Vue 2 添加了
v-else-if
。 -
Vue 2 中,可以使用
key
管理v-if
上不可复用的元素(key
必须唯一 ):<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="username-input"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address" key="email-input"> </template>
没有添加
key
属性的元素仍然会被复用。
v-show
- Vue 2 完全放弃了
v-show
中的v-else
语法,同时v-show
也不支持<template>
语法。
v-for
-
Vue 2 添加了对象迭代
v-for
:-
可以用
v-for
通过一个对象的属性来迭代。<ul id="repeat-object" class="demo"> <li v-for="value in object"> {{ value }} </li> </ul>
new Vue({ el: '#repeat-object', data: { object: { FirstName: 'John', LastName: 'Doe', Age: 30 } } })
-
也可以提供第二个参数为键名,第三个参数为索引。
<div v-for="(value, key) in object"> {{ key }} : {{ value }} </div>
<div v-for="(value, key, index) in object"> {{ index }}. {{ key }} : {{ value }} </div>
-
-
Vue 2 还提供了整数迭代
v-for
:<div> <span v-for="n in 10">{{ n }}</span> </div>
-
Vue 2 还提供了组件
v-for
。但是组件v-for
不能自动传递数据到组件里,因为组件有自己的独立作用域,要使用props
传递。<my-component v-for="(item, index) in items" v-bind:item="item" v-bind:index="index"> </my-component>
key
-
从 Vue 2 开始,Vue 不再需要用户显式使用 Vue 1 提供的
track-by="$index"
语法,而是提供了一套类似的“就地复用”策略。但是这个策略只适用于不依赖子组件状态或者临时 DOM 状态(例如:表单输入值)的列表渲染输出。 -
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,要为每项提供一个唯一
key
属性。理想的key
值是每项都有唯一id
。这个特殊的属性相当于 Vue 1.x 的track-by
,但它的工作方式类似于一个属性,所以要用v-bind
来绑定动态值。<div v-for="item in items" :key="item.id"> <!-- 内容 --> </div>
-
建议尽可能使用
v-for
来提供key
,除非迭代 DOM 内容足够简单,或者你是故意要依赖于默认行为来获得性能提升。(通常情况下,所有自定义组件和依赖于临时 DOM 状态的组件都应当绑定key
属性。)
事件处理器
事件修饰符
-
Vue 2 相比 Vue 1 提供了更丰富的事件修饰符:
<!-- 阻止单击事件冒泡 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件侦听器时使用事件捕获模式 --> <div v-on:click.capture="doThis">...</div> <!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 --> <div v-on:click.self="doThat">...</div> <!-- 2.14 新增:点击事件将只会触发一次 --> <a v-on:click.once="doThis"></a>
.once
修饰符还能被用到自定义的组件事件上。
按键修饰符
-
Vue 2 相比 Vue 1 提供了更丰富的按键别名。
-
Vue 2 修改了自定义按键修饰符别名的方式 - 使用
Vue.config.keyCodes
:// 可以使用 v-on:keyup.f1 Vue.config.keyCodes.f1 = 112
表单控件绑定
修饰符
-
Vue 2 修改了绑定修饰符的方法:
<input v-model.number="age" type="number"> // type="number" 是原生 DOM 属性。
-
Vue 2 添加了
.trim
修饰符,用于去掉输入字符串首尾的空格。<input v-model.trim="msg">
v-model
与组件
- 可以说 Vue 2 实现的
v-model
才是真正的v-model
。 - Vue 2 的组件系统允许你创建一个具有自定义行为可复用的
input
类型,这些input
类型甚至可以和v-model
一起使用!要了解更多,请参阅自定义input
类型
组件
使用组件
-
在 Vue 2 中,对 DOM 模板的验证放宽了。对于一些 HTML 有限制的元素,在下列环境下将不受限制:
<script type="text/x-template">
- JavaScript 内联模板字符串
-
.vue
组件
-
data
必须是函数:在 Vue 2 中,data
被强制要求成了函数。
Prop
- 在 Vue 2 中使用字符串模板时,不需要将 camelCase 转换成 kebab-case
- Vue 2 不允许在子组件内部改变
prop
,即便使用双向绑定也不行。应当通过子组件触发event
由父组件捕获,或者其他方式更改prop
。- 在 JavaScript 中对象和数组是引用类型,指向一个内存空间。所以如果
prop
是一个对象或数组,在子组件内部改变它会影响父组件的状态。
- 在 JavaScript 中对象和数组是引用类型,指向一个内存空间。所以如果
自定义组件
-
在 Vue 2 中,不能用
$on
侦听子组件抛出的事件,必须要在模板里直接用v-on
绑定。 -
Vue 2 移除了
Vue
选项中的events
选项。 -
在 Vue 2 中,如果要在某个组件的根元素上监听原生事件,要使用
.native
修饰v-on
<my-component v-on:click.native="doTheThing"></my-component>
-
在 Vue 2 中,
v-model
实现了一个语法糖:在自定义的 Input 组件中使用v-model
进行数据绑定时,组件内要接收一个value
属性,并在有新的value
时触发input
事件。其余的事情v-model
会自动处理。一个官方示例(使用的是字符串模板):<currency-input v-model="price"></currency-input>
Vue.component('currency-input', { template: '\ <span>\ $\ <input\ ref="input"\ v-bind:value="value"\ v-on:input="updateValue($event.target.value)"\ >\ </span>\ ', props: ['value'], methods: { // 不是直接更新值,而是使用此方法来对输入值进行格式化和位数限制 updateValue: function (value) { var formattedValue = value // 删除两侧的空格符 .trim() // 保留 2 小数位 .slice(0, value.indexOf('.') + 3) // 如果值不统一,手动覆盖以保持一致 if (formattedValue !== value) { this.$refs.input.value = formattedValue } // 通过 input 事件发出数值 this.$emit('input', Number(formattedValue)) } } })
-
Vue 2 取消了
$dispatch
和$broadcast
,可以使用bus
替代。 -
非父子组件通信:
-
Vue 2 给出了一个新的思路用于处理简单场景的组件通信:使用一个空的 Vue 实例当做中央事件总线:
var bus = new Vue()
// 触发组件 A 中的事件 bus.$emit('id-selected', 1)
// 在组件 B 创建的钩子中监听事件 bus.$on('id-selected', function (id) { // ... })
-
使用 slot 分发内容
-
Vue 2 提供了作用域插槽,用作使用一个(能够传递数据到)可重用模板替换已渲染元素。在子组件中,只需要将数据传递到插槽,就像使用
prop
一样:<div class="child"> <slot text="hello from child"></slot> </div>
在父级中,具有特殊属性
scope
的<template>
元素,表示它是作用域插槽的模板。scope
的值对应一个临时变量名,此变量接收从子组件中传递的prop
对象。<div class="parent"> <child> <template scope="props"> <span>hello from parent</span> <span>{{ props.text }}</span> </template> </child> </div>
渲染结果:
<div class="parent"> <div class="child"> <span>hello from parent</span> <span>hello from child</span> </div> </div>
-
一个作用域插槽更实用的例子:
<my-awesome-list :items="items"> <!-- 作用域插槽也可以在这里命名 --> <template slot="item" scope="props"> <li class="my-fancy-item">{{ props.text }}</li> </template> </my-awesome-list>
列表组件模板:
<ul> <slot name="item" v-for="item in items" :text="item.text"> <!-- fallback content here --> </slot> </ul> // 这边应该定义了一个叫 items 的 prop ,然后父组件 :items="items" 传进去。
-
在 Vue 2 中
keep-alive
变成元素了,而不是一个指令或者参数。<keep-alive> <component :is="currentView"> <!-- 非活动组件将被缓存! --> </component> </keep-alive>
杂项
-
Vue 2 修改了
v-ref
的用法,并合并了v-el
,新的属性叫ref
,用于访问子组件(访问的方式不变):<div id="parent"> <user-profile ref="profile"></user-profile> </div>
var parent = new Vue({ el: '#parent' }) // 访问子组件 var child = parent.$refs.profile
- 要注意的是,
$refs
只在组件渲染完成后才填充,而且是非响应式的。所以应当避免在模板或计算属性中使用$refs
。
- 要注意的是,
-
Vue 2 引入了一种新的定义模板的方式: X-Template
<script type="text/x-template" id="hello-world-template"> <p>Hello hello hello</p> </script>
Vue.component('hello-world', { template: '#hello-world-template' })
- 这在有很多模版或者小的应用中有用,否则应该避免使用,因为它将模版和组件的其他定义隔离了。
Render 函数
-
Vue 2 新增了 Render 函数,一个例子:
Vue.component('anchored-heading', { render: function (createElement) { return createElement( 'h' + this.level, // tag name 标签名称 this.$slots.default // 子组件中的阵列 ) }, props: { level: { type: Number, required: true } } })
- 需要知道当你不使用
slot
属性向组件中传递内容时, 这些子元素被存储在组件实例中的$slots.default
中。详见 instance properties API
- 需要知道当你不使用
-
更详细的内容可以参考官方文档。
自定义指令
钩子函数
- Vue 2 扩充了指令的钩子函数:
-
bind
: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。 -
inserted
: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。 -
update
: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。 -
componentUpdated
: 被绑定元素所在模板完成一次更新周期时调用。 -
unbind
: 只调用一次, 指令与元素解绑时调用。
-
- 有关钩子函数的详细信息可以查看官方文档。