指令
指令(Directives)是带有v-
前缀的特殊属性。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM。
v-if条件判断
Title
Paragraph 1
Paragraph 2
元素当做不可见的包裹元素
A
B
Not A/B/C
v-if是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
v-show显示判断
Hello!
与v-if
不同,v-show只是进行CSS的变换。
v-bind属性绑定
...
绑定url到href,当url有变化可响应dom重渲染,可缩写成
...
v-on事件绑定
...
绑定doSomething函数到a标签的点击事件,可缩写成
...
v-for循环
可循环渲染动态选项,数组形式
与react不同,react需要使用map方法遍历返回组件,vue直接把循环挂在标签属性上。
对象形式
data: {
options: {
jock: '佐客',
tom: '汤姆',
miko: '咪口'
}
}
修饰符
修饰符(Modifiers)是以半角句号.
指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent
修饰符告诉v-on
指令对于触发的事件调用 event.preventDefault()
:
事件修饰符
-
.prevent
=>event.preventDefault()
-
.stop
=>event.stopPropagation()
-
.capture
使用事件捕获 -
.self
只当在 event.target 是当前元素自身时触发处理函数,即事件不是从内部元素触发的 -
.once
事件只触发一次
按键修饰符
全部的按键别名:
- .enter
- .tab
- .delete (捕获“删除”和“退格”键)
- .esc
- .space
- .up
- .down
- .left
- .right
系统修饰键
- .ctrl
- .alt
- .shift
- .meta
在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。
.exact 修饰符
.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。
鼠标按钮修饰符
- .left
- .right
- .middle
这些修饰符会限制处理函数仅响应特定的鼠标按钮。
计算属性computed
基础例子如下
Original message: "{{ message }}"
Computed reversed message: "{{ reversedMessage }}"
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
computed下的reversedMessage
方法依赖data下的变量message,当message发生变量,reversedMessage会重新计算结果,与mobx中的computed的作用相同。
以上例子也可通过method
属性完成,如下
Reversed message: "{{ reversedMessage() }}"
// 在组件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
不同的是计算属性是基于它们的依赖进行缓存的。
计算属性computed
也可同时设置setter和getter方法取代直接写funciton,如下:
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]
}
}
}
侦听器watch
new Vue({
data: {
watchData: ''
},
watch: {
watchData: function (newData, oldData) {
// doSomething
}
}
})
Class与Style
class的对象形式,与classnames模块类似
class数组形式
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
class对象与数组混合使用
在组件上使用
Vue.component('my-component', {
template: '
'
})
结果为:
style对象形式
data: {
activeColor: 'red',
fontSize: 30
}
style数组形式
表单输入绑定
v-model
指令在表单input
及textarea
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。v-model会忽略所有表单元素的value、checked、selected特性的初始值而总是将Vue实例的数据作为数据来源。你应该通过JavaScript在组件的data选项中声明初始值。
如:
Message is: {{ message }}
多行文本
Multiline message is:
{{ message }}
.lazy
在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步。你可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步:
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:
组件
组件 (Component) 是Vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用is
特性进行了扩展的原生 HTML 元素。
请注意,对于自定义标签的命名Vue.js不强制遵循W3C规则 (小写,并且包含一个短杠),尽管这被认为是最佳实践。
全局注册组件
Vue.component('my-component', {
// 选项
})
局部注册组件
var Child = {
template: 'A custom component!'
}
new Vue({
// ...
components: {
// 将只在父组件模板中可用
'my-component': Child
}
})
由于html元素之间不能随意嵌套,如table、ul、ol,所以在自定义组件中使用这些受限制的元素时会导致一些问题,例如:
...
自定义组件is
特性:
但是如果代码来自以下字符串模板,则没有这个限制:
- JavaScript 内联模板字符串
- .vue 组件
data
必须是函数
声明的组件data必须为一个函数并返回响应数据,否则会出现警告并停止运行,声明比如类似如下:
var data = { counter: 0 }
Vue.component('simple-counter', {
template: '',
// 技术上 data 的确是一个函数了,因此 Vue 不会警告,
// 但是我们却给每个组件实例返回了同一个对象的引用
data: function () {
return {
counter: 0
}
}
})
new Vue({
el: '#example-2'
})
Prop
与react类似,prop为传入组件的参数,属于单向数据流,如果是绑定了父组件的data,变化会引起DOM重渲染,声明组件时候需要声明预期的props,如下:
Vue.component('child', {
// 声明 props
props: ['message'],
// 就像 data 一样,prop 也可以在模板中使用
// 同样也可以在 vm 实例中通过 this.message 来使用
template: '{{ message }}'
})
由于HTML不区分大小写,声明prop的时候我们需要声明为camelCase
驼峰命名形式,但是传入的时候必须写成kebab-case
短横线分隔式命名。如下:
Vue.component('child', {
// 在 JavaScript 中使用 camelCase
props: ['myMessage'],
template: '{{ myMessage }}'
})
动态Prop
可以用 v-bind 来动态地将 prop 绑定到父组件的数据。每当父组件的数据变化时,该变化也会传导给子组件:
new Vue({
el: '#prop-example-2',
data: {
parentMsg: 'Message from parent'
}
})
prop声明时可以指定特定规则,规范prop的格式,如:
Vue.component('example', {
props: {
// 基础类型检测 (`null` 指允许任何类型)
propA: Number,
// 可能是多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数值且有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}
})
type也可以是一个自定义构造器函数,使用instanceof
检测。
动态组件
通过使用保留的is
特性进行动态绑定,你可以在同一个挂载点动态切换多个组件:
var vm = new Vue({
el: '#example',
data: {
currentView: 'home'
},
components: {
home: { /* ... */ },
posts: { /* ... */ },
archive: { /* ... */ }
}
})
也可以直接绑定到组件对象上:
var Home = {
template: 'Welcome home!
'
}
var vm = new Vue({
el: '#example',
data: {
currentView: Home
}
})
插槽
假定 my-component 组件有如下模板:
我是子组件的标题
只有在没有要分发的内容时才会显示。
父组件模板:
我是父组件的标题
这是一些初始内容
这是更多的初始内容
渲染结果:
我是父组件的标题
我是子组件的标题
这是一些初始内容
这是更多的初始内容
例如,假定我们有一个 app-layout 组件,它的模板为:
父组件模板:
这里可能是一个页面标题
主要内容的一个段落。
另一个主要段落。
这里有一些联系信息
渲染结果为:
这里可能是一个页面标题
主要内容的一个段落。
另一个主要段落。
在设计组合使用的组件时,内容分发 API 是非常有用的机制。
子组件引用
但是有时仍然需要在JavaScript中直接访问子组件。与react类似,可以使用ref
为子组件指定一个引用ID。例如:
var parent = new Vue({ el: '#parent' })
// 访问子组件实例
var child = parent.$refs.profile
当ref和v-for一起使用时,获取到的引用会是一个数组,包含和循环数据源对应的子组件。
自定义事件
使用 v-on 绑定自定义事件
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName, optionalPayload) 触发事件
例子如下:
{{ msg }}
Vue.component('button-message', {
template: `
`,
data: function () {
return {
message: 'test message'
}
},
methods: {
handleSendMessage: function () {
this.$emit('message', { message: this.message })
}
}
})
new Vue({
el: '#message-event-example',
data: {
messages: []
},
methods: {
handleMessage: function (payload) {
this.messages.push(payload.message)
}
}
})
给组件绑定原生事件
可以使用v-on的修饰符.native
。例如:
.sync修饰符
该修饰符可以让一个prop变成"双向绑定",如下
当comp内修改了foo变量时,父组件的foo也会同时被修改,该修饰符Vue2.0后被移除,在Vue2.3又被引入,只是这次它只是作为一个编译时的语法糖存在。它会被扩展为一个自动更新父组件属性的 v-on 监听器。如上例子会被扩展成:
bar = val">
当子组件需要更新 foo 的值时,它需要显式地触发一个更新事件:
this.$emit('update:foo', newValue)
自定义组件的v-model
默认情况下,一个组件的 v-model 会使用 value prop 和 input 事件。但是诸如单选框、复选框之类的输入类型可能把 value 用作了别的目的。model 选项可以避免这样的冲突:
Vue.component('my-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean,
// 这样就允许拿 `value` 这个 prop 做其它事了
value: String
},
// ...
})
上述代码等价于:
{ foo = val }"
value="some value">