vue API 知识点(2)---选项总结

张宁187 2020-11-09 00:05:07
vue API 选项 知识 知识点


一、选项 / 数据

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 来进行双向绑定了(多看一下示例就明白了)

 

版权声明
本文为[张宁187]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/zhangning187/p/vueapixxzj.html

  1. [front end -- JavaScript] knowledge point (IV) -- memory leakage in the project (I)
  2. This mechanism in JS
  3. Vue 3.0 source code learning 1 --- rendering process of components
  4. Learning the realization of canvas and simple drawing
  5. gin里获取http请求过来的参数
  6. vue3的新特性
  7. Get the parameters from HTTP request in gin
  8. New features of vue3
  9. vue-cli 引入腾讯地图(最新 api,rocketmq原理面试
  10. Vue 学习笔记(3,免费Java高级工程师学习资源
  11. Vue 学习笔记(2,Java编程视频教程
  12. Vue cli introduces Tencent maps (the latest API, rocketmq)
  13. Vue learning notes (3, free Java senior engineer learning resources)
  14. Vue learning notes (2, Java programming video tutorial)
  15. 【Vue】—props属性
  16. 【Vue】—创建组件
  17. [Vue] - props attribute
  18. [Vue] - create component
  19. 浅谈vue响应式原理及发布订阅模式和观察者模式
  20. On Vue responsive principle, publish subscribe mode and observer mode
  21. 浅谈vue响应式原理及发布订阅模式和观察者模式
  22. On Vue responsive principle, publish subscribe mode and observer mode
  23. Xiaobai can understand it. It only takes 4 steps to solve the problem of Vue keep alive cache component
  24. Publish, subscribe and observer of design patterns
  25. Summary of common content added in ES6 + (II)
  26. No.8 Vue element admin learning (III) vuex learning and login method analysis
  27. Write a mini webpack project construction tool
  28. Shopping cart (front-end static page preparation)
  29. Introduction to the fluent platform
  30. Webpack5 cache
  31. The difference between drop-down box select option and datalist
  32. CSS review (III)
  33. Node.js学习笔记【七】
  34. Node.js learning notes [VII]
  35. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  36. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  37. 【JQuery框架,Java编程教程视频下载
  38. [jQuery framework, Java programming tutorial video download
  39. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  40. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  41. 【Vue,阿里P8大佬亲自教你
  42. 【Vue基础知识总结 5,字节跳动算法工程师面试经验
  43. [Vue, Ali P8 teaches you personally
  44. [Vue basic knowledge summary 5. Interview experience of byte beating Algorithm Engineer
  45. 【问题记录】- 谷歌浏览器 Html生成PDF
  46. [problem record] - PDF generated by Google browser HTML
  47. 【问题记录】- 谷歌浏览器 Html生成PDF
  48. [problem record] - PDF generated by Google browser HTML
  49. 【JavaScript】查漏补缺 —数组中reduce()方法
  50. [JavaScript] leak checking and defect filling - reduce() method in array
  51. 【重识 HTML (3),350道Java面试真题分享
  52. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  53. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  54. [re recognize HTML (3) and share 350 real Java interview questions
  55. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  56. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  57. 【重识 HTML ,nginx面试题阿里
  58. 【重识 HTML (4),ELK原来这么简单
  59. [re recognize HTML, nginx interview questions]
  60. [re recognize HTML (4). Elk is so simple