vue中的定义的data为什么是函数?

高频面试题:vue中的data为啥是函数?

答案是:是不是一定是函数,得看场景。并且,也无需担心什么时候该将data写为函数还是对象,因为vue内部已经做了处理,并在控制台输出错误信息。

一、new Vue场景

new Vue({el: "#app",// 方式一:对象data: {obj: {name: "qb",}},// 方式二:工厂函数// data () {// return {// obj: {// name: "qb",// }// }// },template: `<div>{{obj.name}}</div>`
}); 

这种场景主要为项目入口或者多个html页面各实例化一个Vue时,这里的data即可用对象的形式,也可用工厂函数返回对象的形式。因为,这里的data只会出现一次,不存在重复引用而引起的数据污染问题。

二、组件场景

Vue.component("countComponent", {data() {return {count: 1};},template: `<div><button @click='changeCount'>递增</button><span>{{count}}</span></div>`,methods: {changeCount() {this.count++;}}
});

new Vue({el: "#app",template: `<div><countComponent></countComponent><countComponent></countComponent></div>`
}); 

首先定义全局组件countComponent,然后将该组件重复使用两次,当定义全局组件的时候,会执行Vuecomponent方法:

// ASSET_TYPES定义在文件shared/constants.js文件中
export const ASSET_TYPES = ['component','directive','filter'
]

// 以下ASSET_TYPES遍历绑定方法的定义在initGlobalAPI(Vue)全局方法挂载阶段完成
import { ASSET_TYPES } from 'shared/constants'
import { isPlainObject, validateComponentName } from '../util/index'
export function initAssetRegisters (Vue: GlobalAPI) {/** * Create asset registration methods. */ASSET_TYPES.forEach(type => {Vue[type] = function ( id: string,definition: Function | Object ): Function | Object | void {if (!definition) {return this.options[type + 's'][id]} else {/* istanbul ignore if */if (process.env.NODE_ENV !== 'production' && type === 'component') {validateComponentName(id)}if (type === 'component' && isPlainObject(definition)) {definition.name = definition.name || iddefinition = this.options._base.extend(definition)}if (type === 'directive' && typeof definition === 'function') {definition = { bind: definition, update: definition }}this.options[type + 's'][id] = definitionreturn definition}}})
} 

这里的场景是component,那么会执行到definition = this.options._base.extend(definition)进行组件构造函数的实现,这里的this.options._base就是构造函数Vueextend方法为:

//Vue.extend 方法的定义在initGlobalAPI(Vue)全局方法挂载阶段完成
export function initExtend (Vue: GlobalAPI) {Vue.extend = function (extendOptions: Object): Function {extendOptions = extendOptions || {}const Super = thisconst SuperId = Super.cidconst cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})if (cachedCtors[SuperId]) {return cachedCtors[SuperId]}const name = extendOptions.name || Super.options.nameif (process.env.NODE_ENV !== 'production' && name) {validateComponentName(name)}const Sub = function VueComponent (options) {this._init(options)}Sub.prototype = Object.create(Super.prototype)Sub.prototype.constructor = SubSub.cid = cid++Sub.options = mergeOptions(Super.options,extendOptions)// ...}
} 

定义完组件构造函数Sub后,在为其合并options时,会执行到mergeOptions

/**
 * Merge two option objects into a new one.
 * Core utility used in both instantiation and inheritance.
 */
export function mergeOptions (parent: Object,child: Object,vm?: Component
): Object {// ...const options = {}let keyfor (key in parent) {mergeField(key)}for (key in child) {if (!hasOwn(parent, key)) {mergeField(key)}}function mergeField (key) {const strat = strats[key] || defaultStratoptions[key] = strat(parent[key], child[key], vm, key)}return options
} 

在当前例子中,会通过const options = {}定义一个空对象,然后分别将parentchild上的属性合并到options上,此时data的合并策略为:

strats.data = function (parentVal,childVal,vm
) {if (!vm) {if (childVal && typeof childVal !== 'function') {process.env.NODE_ENV !== 'production' && warn('The "data" option should be a function ' +'that returns a per-instance value in component ' +'definitions.',vm);return parentVal}return mergeDataOrFn(parentVal, childVal)}return mergeDataOrFn(parentVal, childVal, vm)
}; 

这里childVal类型为object,即typeof childVal !== 'function'成立,进而在开发环境会在控制台输出警告并且直接返回parentVal,说明这里压根就没有把childVal中的任何data信息合并到options中去。

总结

vue中已经帮我们控制台输出警告,并且不会让组件中的data合并到options中去,那么,很友好的处理了开发者的强行将data写成对象的可能性。

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值