赞
踩
Vue 2.0 出来也有一段时间了,作为一个有志向的全面发展好青年,在征服 Vue 1.x,React,React Native 后,为了之后能更快迁移公司的项目到 Vue 2.x,于是决定先看看 Vue 2.0。
鉴于部分读者可能不了解 Vue,先简单看看各种特性。
本文假设你有一定的 HTML 基础,并熟悉一种或以上编程语言(那就能看懂 JS 了)。
Vue 提供了一堆数据绑定语法。
Vue 实例,实则也就是 ViewModel(数据 + 函数),都是通过构造函数 Vue 创建的:
- var data = { a: 1 }
- var vm = new Vue({
- el: '#example',
- data: data,
- created: function () {
- // `this` 指向 vm 实例
- console.log('a is: ' + this.a)
- }
- })
- vm.$data === data // -> true
- vm.$el === document.getElementById('example') // -> true
- // $watch 是一个实例方法
- vm.$watch('a', function (newVal, oldVal) {
- // 这个回调会在 `vm.a` 改变的时候触发
- })
riginal message: "{{ message }}" Computed reversed message: "{{ reversedMessage }}" var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 一个 computed getter reversedMessage: function () { // `this` 指向 vm 实例 return this.message.split('').reverse().join('') } } })
和使用 method 的区别在于,计算属性根据它的依赖被缓存,即如果 message 没有被修改,下次 get 不会进行重复计算,而 method 则每次调用都会重新计算。这也意味着如 Date.now() 这样返回的计算属性会永远得不到更新。
默认情况下,计算属性只有一个 getter,我们也可以给它加上 setter:
- computed: {
- fullName: {
- // getter
- get: function () {
- return this.firstName + ' ' + this.lastName
- },
- // setter
- set: function (newValue) {
- var names = newValue.split(' ')
- this.firstName = names[0]
- this.lastName = names[names.length - 1]
- }
- }
- }
如此,当我们调用 vm.fullName = 'MarkZhai' 的时候,firstName 和 lastName 都会被更新。
Vue 的 watch 也可以用来做类似的事:
{{ fullName }} var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, watch: { firstName: function (val) { this.fullName = val + ' ' + this.lastName }, lastName: function (val) { this.fullName = this.firstName + ' ' + val } } })
- var vm = new Vue({
- el: '#demo',
- data: {
- firstName: 'Foo',
- lastName: 'Bar'
- },
- computed: {
- fullName: function () {
- return this.firstName + ' ' + this.lastName
- }
- }
- })
如此,使用 watch 让我们可以进行异步操作(访问 API),限制操作间隔,并设置中间状态直到获得了真正的答案。
除了使用 watch option,也可以用 vm.$watch API。
除了数据绑定,常见的还有 style、class 的绑定(正如很久以前在 JQuery 中常用的)。
我们可以传递一个对象给 v-bind:class 来动态切换 classes:
对应的 active 和 text-danger 则通过 data 传递过来。
我们也可直接通过 data 把 class 传递过来
- data: {
- classObject: {
- active: true,
- 'text-danger': false
- }
- }
当然我们也能使用上面提到的 computed 来进行对应属性,如 active 的计算。
可以直接传递一个数组给 v-bind:class:
- data: {
- activeClass: 'active',
- errorClass: 'text-danger'
- }
跟 class 差不多:
或者直接绑定到 style:
- data: {
- styleObject: {
- color: 'red',
- fontSize: '13px'
- }
- }
类似的,也有数组绑定。
其实就是个标签啦
- Yes
-
-
- Yes
-
- No
因为 v-if 必须附加到一个单一 element 上,那如果我们想切换多个元素呢?可以使用 template 元素:
也可以用 v-show 来做条件显示的逻辑,
Hello!
区别在于
所以如果切换得较为频繁可以使用 v-show,如果在运行时不太会改变则可以使用 v-if。
其实就是个循环标签啦:
{{ parentMessage }} - {{ index }} - {{ item.message }}
- var example2 = new Vue({
- el: '#example-2',
- data: {
- parentMessage: 'Parent',
- items: [
- { message: 'Foo' },
- { message: 'Bar' }
- ]
- }
- })
跟 v-if 类似,我们也能在 template 上使用 v-for:
也能使用 v-for 遍历对象的属性:
- {{ value }}
-
-
- new Vue({
- el: '#repeat-object',
- data: {
- object: {
- FirstName: 'John',
- LastName: 'Doe',
- Age: 30
- }
- }
- })
看到 value,那肯定还有 key 了:
{{ key }} : {{ value }}
如果再加上 index:
{{ index }}. {{ key }} : {{ value }}
其他还有像是 v-for="n in 10" 这种用法,就不加上例子了。
input 输出内容到 newTodoText,每次点击 enter 都会触发 addNewTodo,然后添加 item 到 todos,触发新的 li 添加进去:
Add a todo Vue.component('todo-item', { template: '\ \ {{ title }}\ X\ \ ', props: ['title'] }) new Vue({ el: '#todo-list-example', data: { newTodoText: '', todos: [ 'Do the dishes', 'Take out the trash', 'Mow the lawn' ] }, methods: { addNewTodo: function () { this.todos.push(this.newTodoText) this.newTodoText = '' } } })
key
当 vue 在更新被 v-for 渲染的列表时候,会使用就地 patch 的策略,而不是根据元素改变的顺序。我们可以提供 key 来做这个排序:
如此,item 会根据 id 来做排序。
这些方法会改变原来的 array,并自动触发 view 的更新。
这几个方法会返回新的 array,如:
- example1.items = example1.items.filter(function (item) {
- return item.message.match(/Foo/)
- })
如果
都是没法触发更新的,需要使用
- Vue.set(example1.items, indexOfItem, newValue)
-
- // Array.prototype.splice`
- example1.items.splice(indexOfItem, 1, newValue)
-
- example1.items.splice(newLength)
配合 computed 以及 filter,或者也可以使用 v-for 的条件渲染:
- {{ n }}
-
-
- data: {
- numbers: [ 1, 2, 3, 4, 5 ]
- },
- methods: {
- even: function (numbers) {
- return numbers.filter(function (number) {
- return number % 2 === 0
- })
- }
- }
使用 v-on 指令监听 DOM 的各种事件,如:
- Add 1
- The button above has been clicked {{ counter }} times.
-
-
-
- var example1 = new Vue({
- el: '#example-1',
- data: {
- counter: 0
- }
- })
除了直接写 JS 语句,也可以直接在 v-on 中调用 methods 中定义的事件,还可以进行传参:
-
- Say hi
- Say what
-
- new Vue({
- el: '#example-3',
- methods: {
- say: function (message) {
- alert(message)
- }
- }
- })
我们可能也希望直接把 event 给传递到方法中(比如在方法里 preventDefault 或者 stopPropagation),也很 easy,直接使用特殊的 $event 变量就行了。
除了像上面这样,在 method 里面对 event 进行操作,我们还可以使用事件修饰符(Event Modifier):
使用如:
-
-
- ...
-
-
-
- ...
通用的有使用 keyCode 的:
其他 alias 别名有
我们也可以自己通过全局的 config 定义其他别名,如:
- // enable v-on:keyup.f1
- Vue.config.keyCodes.f1 = 112
-
- edit me
-
- Message is: {{ message }}
-
如此,用户的输入会直接反映到 data 中的 message,然后更新到
。
多行的用 textarea 替换 input 就行了。
单个的:
-
- {{ checked }}
多个的则可以绑到一个 array :
-
- Jack
-
- John
-
- Mike
-
-
- Checked names: {{ checkedNames }}
-
- One
-
-
-
- Two
-
-
- Picked: {{ picked }}
-
- Selected: {{ selected }}
- Selected: C
多选的在 select 后面加个 multiple,然后对应的会绑定到数组。
还可以结合 v-for 进行动态渲染:
默认地,像上面这样,最后 v-model 绑定到的对象,其值会是一个 静态字符串(或者 true/false),有时候我们想要将其值绑定到一个动态属性,就可以使用 v-bind 来达到目的。
比如对于 input:
-
- // when checked:
- vm.toggle === vm.a
- // when unchecked:
- vm.toggle === vm.b
甚至对象:
-
- // when selected:
- typeof vm.selected // -> 'object'
- vm.selected.number // -> 123
默认地,v-model 在每次 input 事件后都会同步输入到数据。加上 lazy 修饰符后就会在 change 事件后才同步:
会自动把输入转为 number:
这还是挺有用的,因为就算限制了 input 的 type 为 number,元素的 value 仍然会返回 string。
好像不用多说了?大家都懂吧。
现代的前端框架,通常都是组件化的了。整个应用的搭建,其实就是组件的拼接。自然 Vue 也不会忘了这个。
注册一个全局组件,只需要 Vue.component(tagName, options) 即可,如:
- Vue.component('my-component', {
- // options
- })
实际渲染出来的 dom 则定义在 template option 中,如:
- // 注册
- Vue.component('my-component', {
- template: '
-
- A custom component!
-
- '
- })
- // 创建一个根实例
- new Vue({
- el: '#example'
- })
-
局部注册
局部注册只需要放在 Vue 实例中:
- var Child = {
- template: '
- A custom component!
-
- '
- }
- new Vue({
- // ...
- components: {
- // 只在父亲的模板里可用
- 'my-component': Child
- }
- })
当使用 Dom 作为模板(比如使用 el 选项来使用已有内容加载元素),将会受到一些因为 HTML 工作原理而导致的限制,因为 Vue 只能在浏览器解析后才获取模板数据并进行处理。比如
中将不能出现自定义组件,只能通过 is 特殊属性进行规避。可以通过以下方法使用字符串模板,就不会有这些限制:
- Vue.component('hello-world', {
- template: '#hello-world-template'
- })
在极小的应用或者大型模板的 demo 的时候可能会有用,其他情况下应该尽量避免。因为这样会把它和其他模板定义给隔离开。
在 Vue 里面渲染纯净的 HTML 元素是很快的,但有时候你可能需要一个包含了很多静态内容的组件。这种情况下,你可以通过在根元素加上 v-once 指令确保它只被评估了一次然后就被缓存下来了,像是这样:
通过使用 vue-migration-helper 可以快速扫出需要替换的代码。
主要有以下几类:
具体一点的话,像是
$index 现在必须使用 index 了(在 v-for 中显示声明)
不能像以前那样到处用了,只在 {{ }} 中生效,转而用计算属性或者方法吧。
transition 属性被废弃了。可以看看新的 Transitions 文档。
加了全局和离开当前页面的钩子,router-link,router data,等等。
等等等等,要升级还是挺痛苦的。啊,对了 vuex 也升级到 2.0 了。更像 redux 了。心情很复杂
差不多也就是这样了。如果你是一个有一定经验并懂得基本 HTML 和 CSS 的高级工程师,我相信几天你就能看完并上手它了,毕竟对比 React 那一整套东西,还是相对简单的。
- Vue.component('terms-of-service', {
- template: '\
- \
- Terms of Service
-
- \
- ... 很多静态内容 ...\
-
-
- \
- '
- })
原文发布时间为:2016年11月10日
原文作者:掘金
本文来源:掘金 如需转载请联系原作者
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。