属性绑定 [ :attr="" ]:
<!-- 属性绑定 ":title"为"v-bind:"的缩写 -->
<span :title="msg1">
数据绑定:{{ msg2 }}
</span>
事件绑定/事件处理 [ @click="" ]:
<!-- 传递事件,'clickFn1(e)','e.target' "@click"为的"v-on:click"缩写 -->
<div @click="clickFn1"></div>
<!-- 传递参数 -->
<div @click="clickFn1(args)"></div>
<!-- 传递事件及参数 -->
<div @click="clickFn1($event, args)"></div>
<!-- 事件修饰符,使用方法如下 -->
<!-- 阻止单击事件继续传播 -->
<a @click.stop="doThis"></a>
<!-- 更多:
@submit.prevent="onSubmit" 表单提交事件不再重载页面
@click.stop.prevent="doThat" 修饰符可以串联
@submit.prevent 只有修饰符
@click.capture="doThis" 添加事件监听器时使用事件捕获模式,元素自身触发的事件先在此处理,然后才交由内部元素进行处理
@click.self="doThat" 只当在 event.target 是当前元素自身时触发处理函数,即事件不是从内部元素触发的
@click.once="doThis" 只触发一次
-->
<!-- 按键修饰符,更多键盘码或别名见官方文档 -->
<input @keyup.enter="submit">
类(class)绑定 [ :class="" ]:
<!-- class绑定的几种方法 -->
<div :class="{ active: isActive, active2: isActive2 }">'isActive'决定是否使用active类名</div>
<div class="static" :class="{ active: isActive }">与静态类共存</div>
<div v-bind:class="[activeClass, errorClass]">数组形式,数组内均为动态数据,需要静态字符串需要加''</div>
<div v-bind:class="['static', isActive ? activeClass : '']">可使用三元表达式</div>
双向绑定 [ v-model="" ]:
本质是 v-bind 和 事件 的语法糖。
注意:v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将 Vue 实例的数据作为数据来源。
<!-- 显示多行文本请添加样式style="white-space: pre-line;" -->
<p>同步绑定data内的message:{{ message }}</p>
<input v-model="message">
<!-- 修饰符 -->
<!-- 懒同步,在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >
<!-- 转化成number类型后再同步 -->
<input v-model.number="age" type="number">
<!-- 修剪前后空格 -->
<input v-model.trim="msg">
自定义组件的 双向绑定 [ v-model="" ]:
// 假设有如下组件
Vue.component('base-checkbox', {
// model设定数据来源及发送数据源
model: {
prop: 'checked',
event: 'change'
},
// 注意,仍需要在本子组件的props内声明checked
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
// 然后就可以在父组件中使用 v-model 双向绑定数据
<base-checkbox v-model="lovingVue"></base-checkbox>
.sync(上例子的进阶写法): [ $emit('update:***', ***) ]
Vue.component('base-checkbox', {
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('update:change', $event.target.checked)"
>
`
})
// 父组件的 "lovingVue" 与子组件的 "checked" 双向绑定
<base-checkbox :checked.sync="lovingVue"></base-checkbox>
条件渲染 [ v-if="" / v-show="" ]:
<!-- 不具备缓存,每次均重新渲染 -->
<h1 v-if="ok">Yes</h1>
<h1 v-else>No(可不使用)</h1>
<!-- 具备缓存,总是被渲染,display -->
<h1 v-show="ok">Yes</h1>
列表渲染 [ v-for="i in list" ]:
<!-- 迭代对象 -->
<div v-for="(value, key, index) in object" :key="index">
{{ index }}. {{ key }}: {{ value }}
</div>
<!-- 迭代数组 -->
<div v-for="(item, index) in items" :key="item.id">
<!-- 内容 -->
</div>
vue实例特有属性及钩子函数:
// 计算,具有缓存,可减少计算
computed: {
fn1() {return ...}
}
// 方法,与计算类似,但不具备缓存
method: {
fn2() {...}
}
// 监听,方法名为'data'内数据名,假设有'msg:1;count:0'
watch: {
msg(val) {
this.count += val;
}
}
// "创建后"钩子函数
created() { ... }
// "挂载后"钩子函数
mounted() { ... }
// 更多钩子函数见下图
注意, "computed" 内的函数首次执行于 "beforeMount" 钩子函数之后, "mounted" 钩子函数之前。
beforeMount(){ console.log('beforeMount') },
mounted(){ console.log('mounted') },
computed: {
count(){
console.log('computed');
return 1
}
}
/*
* 打印结果:
* beforeMount
* computed
* mounted
*/
computed 内使用 "setter" 和 "getter" :
computed: {
someValue: {
get(){
return this._someValue
},
set(newValue){
// 指定一定操作...
this._someValue = newValue
}
}
}
组件注册: [ components: { ... } ]
// 全局注册组件,<my-component-name> 使用组件
Vue.component('my-component-name', { /* ... */ })
// 局部注册组件,在vue实例内部的component属性注册。<componenetA> 使用组件
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
// 实际使用组件
// 抛出组件
export default {
// js逻辑
}
// 引入组件,并注册到components属性内
import App from './path'
new Vue({
components: { App }
})
"X-Templates" 定义组件:
// 通过一个 id 将模板引用过去
<script type="text/x-template" id="hello-world-template">
<p>Hello hello hello</p>
</script>
// 该方法慎用,这会将模板和该组件的其它定义分离开
Vue.component('hello-world', {
template: '#hello-world-template'
})
"v-once" 创建低开销的静态组件:
// 组件包含了大量静态内容。在根元素上添加 v-once 特性以确保这些内容只计算一次然后缓存起来
Vue.component('terms-of-service', {
template: `
<div v-once>
<h1>Terms of Service</h1>
... a lot of static content ...
</div>
`
})
props用法/props验证:
注意:props内注册的属性大小写不敏感,会把"camelCase"转化成"kebab-case"
// prop用于父组件向子组件传递数据,两种方式注册
// 数组类型
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
// 对象类型,可设定传入数据类型
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 ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
// 父组件传入参数
<blog-post :title="post.title"></blog-post>
自定义事件: [ this.$emit('myEvent') @myEvent="fn" ]
// 可用于子组件向父组件传递数据
// 注册自定义事件,args可省略
this.$emit('myEvent', args);
// 监听触发自定义事件
<my-component @myEvent="doSomething"></my-component>
// .native 修饰符
// 用于绑定标签原生事件
<input v-on:focus.native="onFocus">
// .sync 修饰符
// 实现父组件与子组件的prop双向绑定
<text-document v-bind:title.sync="doc.title"></text-document>
插槽 [ <slot> ] :
// 假设子组件名称为"base-box"
// 子组件定义具名插槽
<div class="base-box">
<slot name="one" style="color:blue"></slot>
<br>
<slot name="two" style="color:red"></slot>
</div>
// 父组件使用子组件的插槽
<base-box>
<template slot="two">这是传递到第二个插槽!</template>
<template slot="one">这是传递到第一个插槽!</template>
</base-box>
动态组件缓存(不重新渲染) [ <keep-alive> ] :
<!-- 每当currentTabComponent发生变化,该组件都会重新渲染,之前选择或输入的内容将消失 -->
<component v-bind:is="currentTabComponent"></component>
<!-- 要使动态组件缓存起来,只需包裹keep-alive标签 -->
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
异步组件:
程序化的事件侦听器: [ 如: this.$once('hook:beforeDestroy', callback) ]
// 程序化销毁第三方对象
mounted: function () {
this.attachDatepicker('startDateInput')
this.attachDatepicker('endDateInput')
},
methods: {
attachDatepicker: function (refName) {
var picker = new Pikaday({ field: this.$refs[refName], format: 'YYYY-MM-DD' })
// 钩子函数的特别用法
this.$once('hook:beforeDestroy', function () {
picker.destroy()
})
}
}
混入: [ mixins ]
官方定义:混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
定义:(与组件创建无异)
var myMixin = {
data() {
return { ... }
},
created() { ... },
methods: { ... }
}
注册:
new Vue({
mixins: [myMixin],
// ...
})
同名属性/方法的优先级:
1. 同名钩子函数都会被调用,且混入对象的钩子函数调用将优先于组件的钩子。
2. 其他同名属性/方法,组件的会覆盖混入对象的。