- provide 选项允许我们指定我们想要提供给后代组件的数据/方法。当多个子/孙组件需要调用同一个父组件的方法时使用。然后在任何后代组件里,我们都可以使用 inject 选项来接收指定的我们想要添加在这个实例上的属性(provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。在 Vue 2.2.1之前inject中的值在prop和data之后初始化)
// 父级组件提供 'foo'
var Provider = {
provide: { // provide 选项应该是一个对象或返回一个对象的函数。
foo: 'bar'
},
// ...
}
// 子组件注入 'foo'
var Child = {
inject: ['foo'],
created () {
console.log(this.foo) // => "bar"
}
// ...
}
// inject 选项应该是数组、对象(该对象的 key 是本地的绑定名,value 是搜索用的 key 或一个包含from和default属性的对象(from 属性是在可用的注入内容中搜索用的 key 、default 属性是降级情况下使用的 value))
inject:{
myFoo:{
from:'foo',
default:'boy' // 与 prop 的默认值类似,你需要对非原始值(数组、对象)使用一个工厂方法
}
}
// 组件
<ul>
<li
v-for="todo in todos"
v-bind:key="todo.id"
>
<!-- 我们为每个 todo 准备了一个插槽,-->
<!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
<slot v-bind:todo="todo">
<!-- 回退的内容 -->
{{ todo.text }}
</slot>
</li>
</ul>
// 使用(获取组件中传出的数据)
<todo-list v-bind:todos="todos">
<!-- 将 `slotProps` 定义为插槽作用域的名字 -->
<template slot-scope="slotProps"> // 这里可以使用解构语法{ todo }
<!-- 为待办项自定义一个模板,-->
<!-- 通过 `slotProps` 定制每个待办项。-->
<span v-if="slotProps.todo.isComplete">✓</span>
{{ slotProps.todo.text }}
</template>
</todo-list>
<text-document v-bind:title.sync="doc.title"></text-document>
// 实际为
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event" // 这里绑定的updata:title由emit触发,$event只想emit传入的第二个参数
></text-document>
...
watch:{
title(newTitle){
this.$emit('update:title', newTitle)
}
}
...
- 一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
<base-checkbox v-model="lovingVue"></base-checkbox>
// 使用 v-model 的时候,这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当 <base-checkbox> 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的属性将会被更新。
- $attrs 属性包含了传递给一个组件的特性名和特性值(即使设置了inheritAttrs: false),和inheritAttrs: false配合,可以手动决定这些特性会被赋予哪个元素。
// $attrs 返回一个绑定到该组件的属性的对象(在api中说明不包括class和style,但是在教程中却包含了class,需要验证)
{
class: 'username-input',
placeholder: 'Enter your username'
}
props
- 不能使用this
- 对一个 prop 进行“双向绑定”。
<text-document v-bind:title.sync="doc.title"></text-document>
// 实际为
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
...
watch:{
title(newTitle){
this.$emit('update:title', newTitle)
}
}
...
- 当我们用一个对象同时设置多个 prop 的时候,也可以使用
<text-document v-bind="doc"></text-document>
。但是不允许绑定字面量对象,例如v-bind=”{ title: doc.title }”
无法正常工作
- 可以传入一个未定义的prop,会自动添加到的根元素上(不一定会添加到根元素上,组件可以通过设置inheritAttrs来禁止绑定,同时还可以通过$attrs来获取绑定到组件上的属性)。对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。所以如果传入 type="text" 就会替换掉 type="date" 并把它破坏!庆幸的是,class 和 style 特性会稍微智能一些,即两边的值会被合并起来,从而得到最终的值
- 验证,props 会在一个组件实例创建之前进行验证,所以实例的属性 (如 data、computed 等) 在 default(默认值,当是数组或对象是需要函数返回) 或 validator(传入值校验) 函数中是不可用的。
props: {
propA:{
type: Number,
default: 100, // 对象或数组默认值必须从一个工厂函数获取
required: true, // 必传
validator: function (value) { // 自定义验证函数
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
- 如果你想要将一个对象的所有属性都作为 prop 传入,你可以使用不带参数的 v-bind (取代 v-bind:prop-name)
<blog-post v-bind="post"></blog-post>
// 等价于
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
- type可以是下列原生构造函数中的一个String、Number、Boolean、Array、Object、Date、Function、Symbol,还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。prop 的值是否是通过 new Person 创建的。
function Person (firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
Vue.component('blog-post', {
props: {
author: Person
}
})
// 类同于
propA: Number
provide / inject
- provide 选项允许我们指定我们想要提供给后代组件的数据/方法。当多个子/孙组件需要调用同一个父组件的方法时使用。然后在任何后代组件里,我们都可以使用 inject 选项来接收指定的我们想要添加在这个实例上的属性(provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。在 Vue 2.2.1之前inject中的值在prop和data之后初始化)
// 父级组件提供 'foo'
var Provider = {
provide: { // provide 选项应该是一个对象或返回一个对象的函数。
foo: 'bar'
},
// ...
}
// 子组件注入 'foo'
var Child = {
inject: ['foo'],
created () {
console.log(this.foo) // => "bar"
}
// ...
}
// inject 选项应该是数组、对象(该对象的 key 是本地的绑定名,value 是搜索用的 key 或一个包含from和default属性的对象(from 属性是在可用的注入内容中搜索用的 key 、default 属性是降级情况下使用的 value))
inject:{
myFoo:{
from:'foo',
default:'boy' // 与 prop 的默认值类似,你需要对非原始值(数组、对象)使用一个工厂方法
}
}
v-bind
- 当绑定为布尔值flase时,该特性不会绑定给元素
- 当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS 属性时,如 transform,Vue.js 会自动侦测并添加相应的前缀。所以尽量使用
- 从 2.3.0 起你可以为 style 绑定中的属性提供一个包含多个值的数组,这样写只会渲染数组中最后一个被浏览器支持的值。
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
- 如果你想要将一个对象的所有属性都作为 prop 传入,你可以使用不带参数的 v-bind
post = {
id:' ',
title:' '
}
<blog-post v-bind="post"></blog-post>
// 等价于
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
v-model
- 在inpu中,可以使用修饰符.lazy(使用 change 事件进行输入数据同步).number(自动将用户的输入值转为数值类型,原生中即使在 type="number" 时,HTML 输入元素的值也总会返回字符串).trim(自动过滤用户输入的首尾空白字符)
- 下拉菜单选项的value可以绑定为任意内存对象,不一定要是字符串。只要传入相同键值的对象就能够选中下拉项(测试来源于饿了吗组件)
- select下拉菜单,单选为文本,多选为文本数组(option有value时优先绑定)。如果 v-model 表达式的初始值未能匹配任何选项,<select> 元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发 change 事件。因此,更推荐提供一个值为空的禁用选项。
<div id="example-5">
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
- 单选按钮绑定value值
- 复选框可以单独设置选中和未选中时的值
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
<div id='example-3'>
<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>
</div>
new Vue({
el: '#example-3',
data: {
checkedNames: [] //=>['Jack','John']
}
})
- 单个复选框,绑定到布尔值:
<input type="checkbox" id="checkbox" v-model="checked">
选中时checked为true,否则为false。不需要value
- 对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model 不会在输入法组合文字过程中得到更新。如果你也想处理这个过程,请使用 input 事件。当用输入法时能够捕获输入的每个拼音字母
- 一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
<base-checkbox v-model="lovingVue"></base-checkbox>
// 使用 v-model 的时候,这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当 <base-checkbox> 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的属性将会被更新。
// input中
<input v-model="searchText">
// 等价于
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
// 组件中
<custom-input v-model="searchText"></custom-input>
// 等价于
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
// 组件内部定义
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)" // $event.target指向时间对象,input对象有value属性
>
`
})
slot-scope
// 组件
<ul>
<li
v-for="todo in todos"
v-bind:key="todo.id"
>
<!-- 我们为每个 todo 准备了一个插槽,-->
<!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
<slot v-bind:todo="todo">
<!-- 回退的内容 -->
{{ todo.text }}
</slot>
</li>
</ul>
// 使用(获取组件中传出的数据)
<todo-list v-bind:todos="todos">
<!-- 将 `slotProps` 定义为插槽作用域的名字 -->
<template slot-scope="slotProps"> // 这里可以使用解构语法{ todo }
<!-- 为待办项自定义一个模板,-->
<!-- 通过 `slotProps` 定制每个待办项。-->
<span v-if="slotProps.todo.isComplete">✓</span>
{{ slotProps.todo.text }}
</template>
</todo-list>
slot
// 组件
<ul>
<li
v-for="todo in todos"
v-bind:key="todo.id"
>
<!-- 我们为每个 todo 准备了一个插槽,-->
<!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
<slot v-bind:todo="todo">
<!-- 回退的内容 -->
{{ todo.text }}
</slot>
</li>
</ul>
// 使用(获取组件中传出的数据)
<todo-list v-bind:todos="todos">
<!-- 将 `slotProps` 定义为插槽作用域的名字 -->
<template slot-scope="slotProps"> // 这里可以使用解构语法{ todo }
<!-- 为待办项自定义一个模板,-->
<!-- 通过 `slotProps` 定制每个待办项。-->
<span v-if="slotProps.todo.isComplete">✓</span>
{{ slotProps.todo.text }}
</template>
</todo-list>