1、注册组件
<ol>
<!-- 创建一个 todo-item 组件的实例 -->
<todo-item></todo-item>
</ol>
// 定义名为 todo-item 的新组件
Vue.component('todo-item', {
template: '<li>这是个待办项</li>'
})
2、构造器
扩展 Vue 构造器,从而用预定义选项创建可复用的组件构造器
var MyComponent = Vue.extend({
// 扩展选项
})
// 所有的 `MyComponent` 实例都将以预定义的扩展选项被创建
var myComponentInstance = new MyComponent()
Vue.js 组件其实都是被扩展的Vue 实例
3、生命周期
实例生命周期的钩子不同阶段调用,如created、 mounted
、 updated
、destroyed
。钩子的 this
指向调用它的 Vue 实例
4、缩写
<!-- 完整语法 -->
<a v-bind:href="url"></a>
<!-- 缩写 -->
<a :href="url"></a>
<!-- 完整语法 -->
<a v-on:click="doSomething"></a>
<!-- 缩写 -->
<a @click="doSomething"></a>
5、计算属性
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// a computed getter
reversedMessage: function () {
// `this` points to the vm instance
return this.message.split('').reverse().join('')
}
}
})
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]
}
}
}
6、Class
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
<div v-bind:class="[isActive ? activeClass : '', errorClass]">
<div v-bind:class="[{ active: isActive }, errorClass]">
7、Style
<div v-bind:style="styleObject"></div>
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
当 v-bind:style
使用需要特定前缀的 CSS 属性时,如 transform
,Vue.js会自动侦测并添加相应的前缀。
从 2.3开始你可以为 style
绑定中的属性提供一个包含多个值的数组,常用于提供多个带前缀的值:
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">
8、条件渲染
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。不要复用它们,添加一个具有唯一值的 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>
v-show
的元素始终会被渲染并保留在 DOM中。v-show
是简单地切换元素的 CSS属性 display
。
当 v-if与 v-for一起使用时,v-for具有比 v-if更高的优先级。
9、列表渲染
<ul id="example-2">
<li v-for="(item, index) in items">/*in 可以换为of*/
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider"></li>
</template>
</ul>
用 v-for
通过一个对象的属性来迭代
<div v-for="(value, key, index) in object">
{{ index }}. {{ key }} : {{ value }}
</div>
在遍历对象时,是按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下是一致的。
<div>
<span v-for="n in 10">{{ n }}</span>
</div>
v-for不能自动传递数据到组件里,因为组件有自己独立的作用域。为了传递迭代数据到组件里,我们要用 props
Vue.component('todo-item', {
template: `
<li>
{{ title }}
<button v-on:click="$emit('remove')">X</button>
</li>
`,
props: ['title']
})
10、数组更新检测
由于 JavaScript的限制, Vue不能检测以下变动的数组:
1. 当你利用索引直接设置一个项时,例如: vm.items[indexOfItem] = newValue
2. 当你修改数组的长度时,例如: vm.items.length = newLength
解决办法:
//1、
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice`
example1.items.splice(indexOfItem, 1, newValue)
//2、
example1.items.splice(newLength)
11、事件处理器
原生 DOM 事件,可以用特殊变量 $event
把它传入方法
<button v-on:click="warn('Form cannot be submitted yet.', $event)">Submit</button>
// ...
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) event.preventDefault()
alert(message)
}
}
Vue.js 为
v-on
提供了
事件修饰符
。通过由点(.)表示的指令后缀来调用修饰符。
<!-- 阻止单击事件冒泡 -->
<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>
<!-- 在某个组件的根元素上监听一个原生事件 -->
<my-component v-on:click.native="doTheThing"></my-component>
Vue 允许为<!-- 点击事件将只会触发一次(可用于组件上) --> <a v-on:click.once="doThis"></a>
v-on
在监听键盘事件时添加按键修饰符:
<!-- 只有在 keyCode 是 enter 时调用 vm.submit() --> <input v-on:keyup.enter="submit"> <!-- 缩写语法 --> <input @keyup.enter="submit">
全部的按键别名:
.enter
.tab
.delete
(捕获 “删除” 和 “退格” 键).esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
可以通过全局 config.keyCodes 对象自定义按键修饰符别名:
// 可以使用 v-on:keyup.f1
Vue.config.keyCodes.f1 = 112
12、表单控件
v-model
指令在表单控件元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。
v-model
并不关心表单控件初始化所生成的值。因为它会选择 Vue 实例数据来作为具体的值。 对于要求 IME (如中文、 日语、 韩语等) 的语言,你会发现那v-model
不会在 ime 构成中得到更新。如果你也想实现更新,请使用input
事件。<input type="checkbox" id="jack" value="Jack" v-model="checkedNames"> <label for="jack">Jack</label> <input type="checkbox" id="john" value="John" v-model="checkedNames"> <label for="john">John</label> <input type="checkbox" id="mike" value="Mike" v-model="checkedNames"> <label for="mike">Mike</label> <br> <span>Checked names: {{ checkedNames }}</span>
new Vue({ el: '...', data: { checkedNames: [] } })
v-bind
实现绑定 value 到 Vue 实例的一个动态属性上
<input type="checkbox" v-model="toggle" v-bind:true-value="a" v-bind:false-value="b" >
修饰符// 当选中时 vm.toggle === vm.a // 当没有选中时 vm.toggle === vm.b
.lazy
在默认情况下,
v-model
在input
事件中同步输入框的值与数据 (除了 上述 IME 部分),但你可以添加一个修饰符lazy
,从而转变为在change
事件中同步:<!-- 在 "change" 而不是 "input" 事件中更新 --> <input v-model.lazy="msg" >
.trim
如果要自动过滤用户输入的首尾空格,可以添加trim
修饰符到v-model
上过滤输入:.number
如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符number
给v-model
来处理输入值:
13、组件
(1)使用组件
要注册一个全局组件,你可以使用
Vue.component(tagName, options)
。
对于自定义标签名尽管遵循(小写,并且包含一个短杠)Vue.component('my-component', { // 选项 })
通过使用组件实例选项注册,可以使组件仅在另一个实例/组件的作用域中可用:
var Child = { template: '<div>A custom component!</div>' } new Vue({ // ... components: { // <my-component> 将只在父模板可用 'my-component': Child } })
<ul>
,<ol>
,<table>
,<select>
中限制自定义组件
<table> <tr is="my-row"></tr> </table>
应当注意,如果您使用来自以下来源之一的字符串模板,这些限制将不适用:
<script type="text/x-template">
- JavaScript内联模版字符串
.vue
组件
Vue构造器中
data
必须是函数。<div id="example-2">
<simple-counter></simple-counter>
<simple-counter></simple-counter>
<simple-counter></simple-counter>
</div>
Vue.component('simple-counter', {
template: '<button v-on:click="counter += 1">{{ counter }}</button>',
// 技术上 data 的确是一个函数了,因此 Vue 不会警告,
// 但是我们返回给每个组件的实例的却引用了同一个data对象
data: function () {
return {counter:0}
}
})
new Vue({
el: '#example-2'
})
在 Vue.js 中,父子组件的关系可以总结为 props down, events up 。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。
Vue.component('child', {
// 声明 props
props: ['message'],
// 就像 data 一样,prop 可以用在模板内
// 同样也可以在 vm 实例中像 “this.message” 这样使用
template: '<span>{{ message }}</span>'
})
HTML 特性是不区分大小写的。所以,当使用的不是字符串模版,camelCased (驼峰式) 命名的 prop 需要转换为相对应的 kebab-case (短横线隔开式) 命名:<!-- kebab-case in HTML -->
<child my-message="hello!"></child>
Vue.component('child', {
// camelCase in JavaScript
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>'
})
prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。可以定义一个局部变量,并用
prop 的值初始化它:prop验证
Vue.component('example', {
props: {
// 基础类型检测 (`null` 意思是任何类型都可以)String/Number/Boolean/Array/Object/Function
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
检测。(3)自定义事件
子组件通过自定义事件把数据传递回去
每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用
$on(eventName)
监听事件 - 使用
$emit(eventName)
触发事件
Vue的事件系统分离自浏览器的EventTarget API。尽管它们的运行类似,但是
$on
和 $emit
不是addEventListener
和 dispatchEvent
的别名。不能用
$on
侦听子组件抛出的事件,而必须在模板里直接用v-on
绑定,就像以下的例子:
<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
Vue.component('button-counter', {
template: '<button v-on:click="increment">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
},
methods: {
increment: function () {
this.counter += 1
this.$emit('increment')
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
}
}
})
2.3 重新引入了 .sync
修饰符,但是这次它只是作为一个编译时的语法糖存在。它会被扩展为一个自动更新父组件属性的 v-on
侦听器。<comp :foo.sync="bar"></comp>
<comp :foo="bar" @update:foo="val => bar = val"></comp>
当子组件需要更新 foo
的值时,它需要显式地触发一个更新事件:
this.$emit('update:foo', newValue)
(4)Slot分发内容
<slot>
元素可以用一个特殊的属性 name
来配置如何分发内容。多个
slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot
特性的元素。
仍然可以有一个匿名 slot ,它是默认
slot ,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot ,这些找不到匹配的内容片段将被抛弃。
在父级中,具有特殊属性 scope
的 <template>
元素,表示它是作用域插槽的模板。scope
的值对应一个临时变量名,此变量接收从子组件中传递的
prop 对象:
<div class="child">
<slot text="hello from child"></slot>
</div>
<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>