vue API 知识点(2)---选项总结
一、选项 / 数据
1.data
当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例,如果 data 仍然是一个纯碎的对象,则所有的实例将被共享引用同一个数据对象。通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。
2.props
props 可以是数组或者对象,用于接收来自父组件的数据。props 中使用对象可以配置高级选项,类型检测,自定义验证,设置默认值
可以使用以下选项
type:可以是原生构造函数中的一种:String、Number、Boolean、Array、Object、Date、Function、Symbol、任何自定义构造函数,或上述内容组成的数组。会检查一个 prop 是否是给定的类型,否则抛出警告。
default:为 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回
required:Boolean 定义该 prop 是否是必填项
validator:function 自定义验证函数会将该 prop 的值作为唯一的参数带入。返回 false 就给默认值,控制台有警告
props: {
// 检测类型
height: Number,
// 检测类型 + 其他验证
age: {
type: Number,
default: 0,
required: true,
validator: function (value) {
return value >= 0
}
}
}
3.propsData
只用于 new 创建的实例中,创建实例时传递 props,主要作用时方便测试(开发的过程中基本用不到)
4.computed 计算属性
计算属性将被混入到 Vue 实例中,所有 geter 和 setter 的 this 上下文自动地绑定为 Vue 实例
注意如果你为一个计算属性使用了箭头函数,则 this 不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。
计算属性的结果会被缓存,除非依赖的响应式 property 变化才会重新计算。注意,如果某个依赖(必须非响应式 property)在该实例范畴之外,则计算属性是不会被更新的。
<p>a + b 的结果是:{{ count }}</p>
computed: { count(){ return this.a + this.b
}
}
计算属性 vs 方法
<p>a + b 的结果是:{{ count() }}</p>
methods: {
count(){
return this.a + this.b
}
}
我们可以将同一函数定义为一个方法而不是一个计算属性,两种方式的最终结果确实是完全相同的。不同的是计算属性是基于他们的响应式依赖进行缓存的。只在相应响应式依赖发生改变时他们才会重新计算求值。就是说只要 a 或者 b 还没有发生改变,多次访问 count 计算属性会立即返回之前的计算结果,而不必再次执行函数。
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数,
我们为什么需要缓存? 假设我们有一个性能开销比较大的计算属性 A,他需要遍历一个巨大的数组并做大量的计算,然后我们可能有其他的计算属性依赖于 A。如果没有缓存我们将不可避免的多次执行 A 的getter。如果不希望有缓存出现,请用方法代替。
计算属性的 setter
计算属性默认只有 getter ,不过在需要时也可以提供一个 setter
computed: {
str: {
get: function() {
return this.a + this.b
},
set: function(newVlaue) {
var abs = newValue.split(' ')
this.a = abs[0]
this.b = abs[abs.length - 1]
}
}
}
现在运行 this.str = '2 3 4 5'时,setter 会被调用,this.a 和 this.b 也会相应地被更新
5.methods 事件处理
在模板中通过 v-on 定义方法名,在 methods 中定义方法
有时在内联语句处理器中访问原始的 DOM 事件,可以用特殊变量 $event 把它传入方法
<button @click="count(200, $event)">按钮</button>
<button @click="count2">按钮2</button>
methods: {
count: function(val, event) {
if(event) {
event.preventDefault()
}
// ...
},
count2: function(event) {// 如果模板中什么都不传递,在这里可以默认直接接受一个参数就是 dom 对象
if(event) {
event.preventDefault()
}
// ...
}
}
6.watch 监听器
一个对象,键是需要观察的表达式,值是对应回调函数,值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性
值是包括选项的对象,有三个选项
handler:回调函数,即监听到变化时应该执行的函数
deep: Boolean,确认是否深度监听
为了发现对象内部值的变化,可以在选项参数中指定 deep: true 注意监听数组的变更不需要这么做
immediate:Boolean,为true时,将立即以表达式的当前值出发回调(进入页面就开始监听)
watch: {
a(){},
// 该回调会在任何被监听的对象 property 改变时被调用,不论其被嵌套多深
b: {
handler: function(){},
deep: true
},
// 该回调将会在侦听开始之后立即调用
c: {
handler: function(),
immediate: true
},
// 可以传入回调数组,他们会被一一调用
d: [
handle1,
function handle2(){},
{
handler: function handle3(){}
}
]
}
二、选项 / DOM
在开发的过程中很少需要考虑这些东西,看看官网熟悉一下
三、选项 / 生命周期钩子
每个 Vue 实例在被创建时都要经过一系列的初始化过程,设置数据监听,编译模板,实例挂载到 DOM ,数据变化时更新 DOM 等,这里面有一系列的函数,称之为生命周期钩子
1.beforeCreate
在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用,此时组件的选项对象还没有创建,el 和 data 并未初始化,因此无法访问 methods,data,computed 等上的方法和数据
2.created
在实例创建完成之后被立即调用。这一步,实例已经完成以下配置:数据观测(data observer),property 和方法的运算,watch/event 事件回调。然而挂载阶段还没开始,$el property 目前尚不可用。这是一个常用的生命周期,这里面可以调用 methods 中的方法,改变 data 中的数据,并且修改可以通过 vue 的响应式绑定体现在页面上,获取 计算属性 等等,通常我们在这里请求接口中的数据,
3.beforeMount
在挂在之前被调用,相关的 render 函数首次被调用,实例已经完成一下的配置:编译模板,把 data 里面的数据和模板生成 html,完成了 el 和 data 初始化,注意此时还没有挂载到 html 页面上
4.mounted
实例被挂载后被调用,这时 el 被新创建的 vm.$el 替换了。如果跟实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内
注意 mounted 不会保证所有的子组件也一起被挂载,如果希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick
mounted(){
this.$nextTick(function(){
// ...
})
}
5.beforeUpdate
数据更新时调用,发生在虚拟 DOM 打补丁之前,这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行
6.updated
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用 计算属性 或 watcher 取而代之。
注意 updated 不会保证所有子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick(同上)
7.activated
被 keep-alive 缓存的组件激活时调用
该钩子在服务器端渲染期间不被调用
8.deactivated
被 keep-alive 缓存的组件停用时被调用
该钩子在服务器端渲染期间不被调用
9.beforeDestroy
实例销毁之前调用。在这一步,实例仍然完全可用
该钩子在服务器端渲染期间不被调用
10.destroyed
实例销毁后调用,该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁
该钩子在服务器端渲染期间不被调用
11.errorCaptured
当捕获一个来自子孙组件的错误时被调用,此钩子会收到三个参数:错误对象、发生错误的组件实例和一个包含错误来源信息的字符串。此钩子返回 false 以阻止该错误继续向上传播
可以在此钩子中修改组件的状态。因此在捕获错误时,在模板或渲染函数中有一个条件判断来绕过其他内容就很重要,不然该组件可能会进入一个无限的渲染循环
错误传播规则
1.默认情况下,如果全局的 config.errorHandler 被定义,所有的错误仍会发送它,因此这些错误仍然会向单一的分析服务的地方进行汇报。
2.如果一个组建的继承或父级从属链路中存在多个 errorCaptured 钩子,则它们将会被相同的错误一一唤起
3.如果此 errorCaptured 钩子自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的 config.errorHandler
4.一个 errorCaptured 钩子能够返回 false 以阻止错误继续向上传播。本质上是说’这个错误已经被搞定且应该被忽略‘。他会阻止其他任何会被这个错误唤起的 errorCaptured 钩子和全局的 config.errorHandler
四、选项 / 资源
1.directives 自定义指令
2.filters 过滤器
3.components 组件
directives、filters、components 详情在这里有介绍 vue API 知识点(1)---全局 API 总结
五、选项 / 组合
1.parent
指定已创建的实例之父示例,在两者之间建立父子关系。子实例可以用 this.$parent 访问父实例,子实例被推入到父实例的 $children 数组中
我们在开发中,基本上不会使用到 $parent 和 $children 。更多的是使用 props 和 events 实现父子组件通信,
2.mixins 混入
3.extends
允许声明扩展另一个组件,而无需使用 Vue.extend。这主要是为了便于扩展单文件组件
这和 mixins 有点类似
mixins、extends 在这篇文章中有详细的介绍 vue API 知识点(1)---全局 API 总结
4.provide / inject
provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。
解析:就是组件的引入层次过多,我们的子孙组件想要获取祖先组件的资源,可以不使用 props 的方式依次传递给子孙组件,层次太多,代码结构容易混乱。那么就可以使用 provide/inject 来做传递
官方注解
provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。在该对象中你可以使用 Symbols 作为key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作
inject 选项应该是一个字符串数组或一个对象,对象的key是本地的绑定名,
value 是 在可用的注入内容中搜索用的 key(字符串或 Symbol),或一个对象,该对象的
from property 是在可用的诸如内容中搜索用的 key(字符串或 Symbol)
default property 是降级情况下使用的 value
个人解析
provide 是一个对象,或者是一个返回对象的函数,里面就包含要给子孙后代的东西,也就是属性和属性值
inject 一个字符串数组,或者是一个对象。属性值可以是一个对象,包含 from 和 default 默认值
const Child = {
inject: {
foo: {
from: 'bar',
default: 'foo'
}
}
}
from 表示在可用的注入内容中搜索用的 key,default 当然就是默认值
注意:provide 和 inject 绑定并不是可响应的。这是刻意为之的,然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的
官方示例
// 父组件
var Provider = {
provide: {
name: 'zhangning'
},
// ...
} // 子组件注入
var Child = {
inject: ['name'],
created() {
console.log(this.name) // => 'zhangning'
}
}
利用 es 中的 Symbols、函数 provide 和对象 inject
const a = Symbol();
const Parent = {
provide(){
return {
[a]: 'zhangning187'
}
}
} const Child = {
inject: { a },
// ...
}
在新版本中,使用一个注入的值作为一个 property 的默认值
const Child = {
inject: ['name'],
props: {
bar: {
default() {
return this.name
}
}
}
}
使用一个注入的值作为数据入口
const Child = {
inject: ['name'],
data() {
return {
bar: this.name
}
}
}
如果它需要从一个不同名字的 property 注入,则使用 from 来表示其源 property
const Child = {
inject: {
from: 'bar',
default: 'name'
}
}
与 prop 的默认值类似,你需要对非原始值使用一个工厂方法
const Child = {
inject: {
name: {
from: 'bar',
default: () => [1, 2, 3]
}
}
}
在日常的开发中,我们经常会使用 Vuex 做状态管理,但是 vuex 有时候太过于繁琐。如果我们不想使用 vuex,这个时候我们就可以使用 provide/inject 这个方式来代替vuex,在跟组件中传入变量,然后在后代组件中使用即可
// 在跟组件中提供一个非响应式变量给后代组件
export default {
provide() {
return {
text: 'zhangning'
}
}
} // 后代组件注入
export default {
inject: ['text'],
created() {
this.text = 'zhangning187'// 在我们使用 text 的时候它依然是 zhangning,而不是zhangning187
}
}
上面已经讲过,provide 和 inject 绑定并不是可响应的,这是可以为之。当然我们也可以传入一个可响应的对象,那么它的属性也就是可响应的了
也就是说,Vue 不会对 provide 中的变量进行响应式处理。所以要想 inject 接受的变量是响应式的,provide 提供的变量本身就需要是响应式的。
由于组件内部的各种状态就是可响应式的,所以我们直接在根组件中将组件本身注入 provide,此时,我们可以在后代组件中任意访问根组件中的所有状态,根组件就成为了全局状态的容器
// 根组件提供将自身提供给后代组件
export default {
provide() {
return {
app: this
}
},
data() {
return {
text: 'zhangning'
}
}
} // 后代组件 注入 export default {
inject: ['app'],
data(){
return{}
},
created: {
this.app.text = 'zhangning187'// 此时使用 text,它的值就是zhangning187
}
}
当然,我们也可以通过 $root 来获取根节点,但是在团队开发的过程中,如果所有的全局变量都统一定义在根组件中并不合适,而使用 provide/inject 不同模块的入口组件传给各自的后代组件可以完美解决这个问题
Vuex 和 provide/inject 区别在于,Vuex 中的全局状态的每次修改都是可以追踪回溯的,而 provide/inject 中变量的修改是无法控制的,通俗说就是,你不知道是哪个组件修改了这个全局状态。
provide/inject 破坏了我们的单向数据流原则。如果多个后代组件同时依赖于一个祖先组件提供的状态,那么只要有一个组件修改了这个状态,则所有组件都会受到影响。这个使耦合度增加了,让我们的数据变化不可控,在多人的开发过程中,这个可能会变得特别混乱。
以上看起来使用 provide/inject 做全局状态管理好像很危险,所以我们要谨慎使用这个方式。
但是在组件开发的时候,vue 官方提倡我们使用这种方法。例如 elment-ui
六、选项 / 其他
1.name
只有作为组件选项时起作用
允许组件模板递归地调用自身,注意,组件在全局用 Vue.component() 注册时,全局 ID 自动作为组件的 name
指定 name 选项的好处就是便于调试,有名字的组件有更友好的警告信息,当在 vue-devtools 下,未命名组件将显示成<AnonymousComponent>,这很没有语义,通过提供 name 选项,可以获得更有语义信息的组件树
2.delimiters
了解一下就行,通常不会去更改插入分隔符
类型 Array<string>
默认值 ["{{", "}}"]
限制 这个选项只在完整构建版本中的浏览器内编译时可用
改变纯文本插入分隔符
示例
new Vue({
delimiters: ["${", "}"]
})
// 分隔符变成了 ES6 模板字符串的风格
3.functional
了解一下,通常用不到
类型 Boolean
使组件组状态(没有 data)和无实例(没有 this 上下文)。他们用一个简单的 render 函数返回虚拟节点,是他们渲染的代价更小
4.model
允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一下输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突
// 定义一个组件
Vue.component('my-check', {
model: {
prop: 'checked',
event: 'change'
},
props: {
value: String,
checked: {
type: Number,
default: 0
}
}
})
使用
<my-check v-model='foo' value='some value'></my-check>
以上代码相当于
<my-check :checked='foo' @change='value=>{foo = val}' value='some value'></my-check>
我们先了解一下 input 中的 v-model 是怎么实现双向绑定的。
<input type='text' v-model='msg'>
v-model 只是语法糖真正的实现方式
<input type='text' :value='msg' @input='msg=$event.target.value'>
真正的双向绑定是通过监听 input 事件
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件
text 和 textarea 元素使用 value 属性和 input 事件
checkbox 和 radio 使用 checked 属性和 change 事件
select 使用 value 和 change 事件
我们可以自定义输入框组件的 v-model,双向绑定
Vue.component('my-input', {
template: `<input :value='value' @input='updateValue($event.target.value)' type='text'></input>`,
props: ['value'],
methods: {
updateValue(val) {
this.$emit('input', val)
}
}
}) let app = new Vue({
el: '#app',
data(){
message: ''
},
methods: {
handleInput(val) {
this.message = val
}
}
})
<div id='app'>
<my-input :value='message' @input='handleInput'></my-input>
</div>
上面的示例我们可以了解到,默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,所以当我们在一个自定义组件上使用 v-model 并不能实现双向绑定,因为自定义的组件并没有默认的 value 和 input 事件,在使用时,我们需要按照上面那样显式的去声明定义这些东西,这时,选项 model 就派上用场了,在定义组件的时候指定 prop 的值和监听的事件(看到这里,上面写的官网给出的例子也应该可以看明白了)
举例
Vue.component('my-input', {
model: {
prop: 'uname',
event: 'handleChange'
},
props: {
uname: {
type: String,
default: 'zhangning'
}
},
methods: {
updateVal(val) {
this.$emit('handleChange', val)
}
}
})
模板
<template>
<div>
<input type='text' :value='uname' @input='updateVal($event.target.value)'>
</div>
</template>
使用组件
<my-input v-model='name' value='some value'></my-input>
等价于
<my-input :uname='name' @handleChange='val=>{foo = val}' value='some value'></my-input>
上面的示例中我们就可以在自定义的组件中使用 v-model 来进行双向绑定了(多看一下示例就明白了)
vue API 知识点(2)---选项总结的更多相关文章
- vue API 知识点(1)---全局 API 总结
1.Vue.extend(options) 构造器,创建一个 子类 .参数是一个包含组件选项的对象 data 选项是特例,需要注意 在 Vue.extend() 中它必须是一个函数, <div ...
- vue API 知识点(3) --- 实例 总结
一.实例 property 1.vm.$data Vue 实例观察的数据对象,Vue 实例代理了对其 data 对象 property 的的访问 2.vm.$props 当前组件接收到的 props ...
- 记vue API 知识点
1. v-cloak指令:这个指令保持在元素上直到关联实例结束编译.和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标 ...
- vue API 知识点(4) --- 指令、特殊 attribute 、内置组件
一.指令 1.v-text <span v-text="msg"></span> <!-- 两种写法是一样的 --> <span>{ ...
- vue 快速入门 系列 —— 侦测数据的变化 - [vue api 原理]
其他章节请看: vue 快速入门 系列 侦测数据的变化 - [vue api 原理] 前面(侦测数据的变化 - [基本实现])我们已经介绍了新增属性无法被侦测到,以及通过 delete 删除数据也不会 ...
- Vue实例初始化的选项配置对象详解
Vue实例初始化的选项配置对象详解 1. Vue实例的的data对象 介绍 Vue的实例的数据对象data 我们已经用了很多了,数据绑定离不开data里面的数据.也是Vue的核心属性. 它是Vue绑定 ...
- VUE API 重点
VUE API 重点 生命周期方法 每个组件都有生命周期,是向 ReactJs 学习的. computed 在一个组件声明一个人,人有名,人有姓,输入姓和名.((&--&%--& ...
- vue 里面的watch 选项详解
早就想好好写写这个watch了,一直顾不上,因为想深刻的记录一下,其实这些东西只要是好好看看官网的说明,都在里面呢. 虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器.这就是为什么 V ...
- VUE【二、选项和生命周期】
vue对象,类似于一个viewModel,是处理页面显示的数据模型的对象 其中会有很多选项,以下为较常用的: 选项 1.data-数据 vue实例会代理其data对象里的所有属性 2.methods- ...
随机推荐
- 070 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 02 综合案例-数组移位-从键盘接收数据
070 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 02 综合案例-数组移位-从键盘接收数据 本文知识点:综合案例-数组移位-从键盘接收数据 说明:因为时间紧张 ...
- kail使用sunJDK
今天在安装软件的时候报错,提示应使用oracle的JDK,所以鼓捣了一会发现个简单的方法 1.下载安装包解压文件到opttar -xzvf jdk-8u91-linux-x64.tar.gz 2.设置 ...
- matlab一个figure画多个子图,和多个figure画多个图。
参考:https://blog.csdn.net/xiaotao_1/article/details/79024488 1,一个figure画多个子图: figure(10) % define fig ...
- 实验五 Internet与网络工具的使用
实验五 Internet与网络工具的使用 [实验目的]⑴.FTP服务器的架设和客户端的使用. ⑵.使用云盘和云笔记应用 ⑶.运用QQ的远程协助功能. (4).默认安装foxmail软件,进行邮件的收发 ...
- 多测师讲解selenium_alert弹框定位_高级讲师肖sir
from selenium import webdriverfrom time import sleepdrvier=webdriver.Chrome()url=r'F:\dcs\DCS课程安排\se ...
- 多测师讲解selenium ——切换窗口——打印句柄_高级讲师肖sir
(一)同一个窗口打开两个浏览器 from selenium import webdriverfrom time import sleepdrvier=webdriver.Chrome()url='ht ...
- MeteoInfoLab脚本示例:Hamawari-8 netCDF data
示例数据:ftp://ftp.bom.gov.au/anon/sample/catalogue/Satellite/IDE00220.201507140300.nc 该数据的分辨率很高(22000*2 ...
- 【原创】xenomai内核解析--双核系统调用(二)--应用如何区分xenomai/linux系统调用或服务
版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正. 1. 引出问题 上一篇文章xenomai内核解析--双核系统调用(一)以X86处理器为例,分析了xenomai内核调用的流程, ...
- 并发压测 jmeter使用教程
百度网盘下载软件 提取码: 2nur 第一步:首先从jmeter的官网下载jmeter,目前最新版本为4.0,支持的JDK最高为1.8 下载地址: jmeter:http://jmeter.apach ...
- centos下安装mongodb 通过shell脚本
#! /bin/bash yum -y update echo -e "开始安装mongodb\n" download_url=https://fastdl.mongodb.o ...