最近的工作,需要写点类似自己公司内部bms系统的一些web页面。由于不是对外的,一些简单的页面就交给后端自己来完成。为了符合公司整个前端代码风格,研究了下 Vue.js 。
Vue.js 官方文档有中文的,整个上手难度也比较低,看完文档再稍加整合下饿了么的 Element 组件基本就能满足大部分像我这样的需要了。js还是啃大学那会用JQuery的老本,并不是很会。自己又习惯做点md笔记,于是干脆在官方文档的基础上加了一点自己的理解,整理出来share一下,再加上本身就是Javaer的角度,很基础,若对看的人有一点点帮助就算有意义了。
打个照面:
- 自定义标签 嵌入原生HTML标签中去:
Vue.component('todo-item', {
props: ['todo'],
template: '{{ todo.text }} '
})
var app7 = new Vue({
el: '#app-7',
data: {
groceryList: [
{ id: 0, text: '蔬菜' },
{ id: 1, text: '奶酪' },
{ id: 2, text: '随便其它什么人吃的东西' }
]
}
})
完了之后调用:
- 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的:
var vm = new Vue({
// 选项
})
当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
这个自然也是可以控制的:
var obj = {
foo: 'bar'
}
Object.freeze(obj)
new Vue({
el: '#app',
data: obj
})
这里对foo的任何修改不会生效(后话了 这里应该是涉及到js的浅拷贝和深拷贝问题)
new 出来的Vue实例还会暴露出自己的一些属性和方法:通过这写方法和属性,可以操作对应这个new 出来的实例
使用 vm.$watch
形式来操作,具体参见API
-
Vue实例生命周期:
上面的生命周期图比较关键,是理解Vue.js很多地方语法结构的助推剂。整体还算比较清晰明了。
- 一般情况下,使用{{}}引用Vue实例中data域的内容,但是HTML元素标签中并不支持此( {{}} )语法。使用v-bind绑定数据域内内容。(id='xx'形式) 而且{{}}内部支持js语法:
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
- 调用方法去执行计算和调用computed中的方法区别:后者依赖上一次计算后的缓存,只要不需要重新计算(Vue提供支持)就不会重新计算。
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
上面的代码能同时监听firstName, lastName两个data域值。
绑定class样式
这里的绑定比较灵活而且强大:
这样子灵活的将active类绑定到data里面isActive的true/false身上。
然后对应的data如下:
data: {
classObject: {
active: true,
'text-danger': false
}
}
可以注意到这里的 class = 后面是一个json格式的对象,那么直接就可以传一个对象进去了:
data: {
classObject: {
active: true,
'text-danger': false
}
}
主要就是这里用json格式来表达一个js对象
在自定义组件时是一种extend的关系,如下:
Vue.component('my-component', {
template: '
'
})
其等价于
上面是绑定class相关,大致就是js对象绑定和数组字面量绑定。
下面是内联样式相关:
首先仍然是对象语法:
data: {
activeColor: 'red',
fontSize: 30
}
灵活并且直观。不熟悉弱类型脚本语言的情况下,确实需要时间适应这种松散的语法声明。
然后就是直接绑定对象:
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
条件渲染
- 使用template标签(此标签不可见)批量进行渲染:
Title
Paragraph 1
Paragraph 2
上面的例子中,如果条件成立,页面元素将被渲染出来。但template本身不会显示。
也有类似于java中的语法:
A
B
C
Not A/B/C
使用if else-if else语句,页面渲染时使用的是同一个不显示的template元素。一方面意味高效,另一方面可以实现元素的共用:
以上代码,实际上是一个template下面的元素。只会渲染其中之一。意味着这里面包裹的元素若是一致的(比如 input ),那么他们在条件变换时也是共用的,即用户在 input 中输入的内容在条件变化过程中不会改变(毕竟是渲染在同一个 input 下的)。
理解共用的道理比这个语法本身貌似更重要些。
当然Vue也提供了屏蔽这一细节的处理方式:key绑定
上面的内容通过key标记的绑定,就可以实现二次渲染。
- v-show 渲染
使用 v-show 的元素会被动态切换其css的 display 样式。和上面的动态渲染不同。这个dom元素会始终被渲染在dom树中,只是css样式的变换而已。
使用如下:
Hello!
其也不支持 template 语法。
列表渲染
- v-for语句
类似于java中的 foreach 语法。比较简单:
-
{{ item.message }}
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
比java好的地方是这里提供一个 index 可选,获取当前元素的下标(毕竟脚本语言,编译语言中要实现这个功能所牺牲的复杂度想必会更高)
-
{{ parentMessage }} - {{ index }} - {{ item.message }}
var example2 = new Vue({
el: '#example-2',
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
- 如果 for 后面传入的不是数组对象而是其他object,则可以遍历其json格式下的所有属性:
-
{{ value }}
new Vue({
el: '#v-for-object',
data: {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
})
输出会是:
- John
- Doe
- 30
另外,in 前面的参数若是 (value, key) 的形式,则遍历 k-v 键值对:
{{ key }}: {{ value }}
结果显然:
firstName:John
lastName:Doe
age:30
最后是 value, key, index 的复合使用:
{{ index }}. {{ key }}: {{ value }}
- 替换数组
这里使用到一个 变异 非变异 方法的概念:前者就是会改变原数组,后者而是在返回值体现改变的效果。
由于使用Vue进行渲染,就必须保证其能检测到我们的修改。但是第三方框架检测不到原生js数组的一些方法。例子中给出:
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
可以使用vue提供的方法:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
即可。
或者这里使用Vue全局方法: Vue.set
vm.$set(vm.items, indexOfItem, newValue)
另外,使用下面的方法改变长度:
vm.items.splice(newLength)
总之,要响应式的改变dom渲染,就必须让Vue感知到这种变化,这里的注意事项给出了一种值得关注的启发:使用Vue就要关注它全方面的js替代性。
- 添加属性
使用Vue提供的方式:
Vue.set(vm.userProfile, 'age', 27)
vm.$set(vm.userProfile, 'age', 27)
一次赋值多个属性:
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
- 使用类似java匿名内部类的比较函数(或者java8的filter的lambda表达函数)返回数组的过滤对象:
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers: function () {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
{{ n }}
类似的在方法中调用:
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
even: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
{{ n }}
- 更加直接地调用常量:
div>
{{ n }}