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

Elina ·
更新时间:2024-09-20
· 361 次阅读

目录

一、new Vue场景

二、组件场景

总结

高频面试题: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 || id definition = this.options._base.extend(definition) } if (type === 'directive' && typeof definition === 'function') { definition = { bind: definition, update: definition } } this.options[type + 's'][id] = definition return 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 = this const SuperId = Super.cid const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {}) if (cachedCtors[SuperId]) { return cachedCtors[SuperId] } const name = extendOptions.name || Super.options.name if (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 = Sub Sub.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 key for (key in parent) { mergeField(key) } for (key in child) { if (!hasOwn(parent, key)) { mergeField(key) } } function mergeField (key) { const strat = strats[key] || defaultStrat options[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写成对象的可能性。

到此这篇关于vue中定义的data为什么是函数的文章就介绍到这了,更多相关vue中data为什么是函数内容请搜索软件开发网以前的文章或继续浏览下面的相关文章希望大家以后多多支持软件开发网!



data VUE 函数

需要 登录 后方可回复, 如果你还没有账号请 注册新账号