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

 更新时间:2022年09月07日 09:20:39   作者:qb  
这篇文章主要介绍了vue中定义的data为什么是函数,vue中已经帮我们控制台输出警告,并且不会让组件中的data合并到options中去,那么,很友好的处理了开发者的强行将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 || 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为什么是函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vuejs如何解决浏览器切换页面后setInterval计时器停止执行的问题

    vuejs如何解决浏览器切换页面后setInterval计时器停止执行的问题

    setinterval()是定时调用的函数,可按照指定的周期(以毫秒计)来调用函数或计算表达式,这篇文章主要给大家介绍了关于vuejs如何解决浏览器切换页面后setInterval计时器停止执行的问题,需要的朋友可以参考下
    2024-01-01
  • vue自定义弹框效果(确认框、提示框)

    vue自定义弹框效果(确认框、提示框)

    这篇文章主要为大家详细介绍了vue自定义弹框,实现确认框、提示框效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • Vue extend的基本用法(实例详解)

    Vue extend的基本用法(实例详解)

    这篇文章主要介绍了Vue extend的基本用法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • Vue3的效率提升主要表现在哪些方面示例解析

    Vue3的效率提升主要表现在哪些方面示例解析

    Vue3带来了许多性能优化和效率提升的特性,本文将重点讨论Vue3在静态提升、预字符串化、缓存事件处理函数、Block Tree和PatchFlag方面的改进,我们将通过对比Vue2和Vue3的编译结果来说明这些方面的效率提升
    2023-12-12
  • vue复杂表格单元格合并根据数据动态合并方式

    vue复杂表格单元格合并根据数据动态合并方式

    这篇文章主要介绍了vue复杂表格单元格合并根据数据动态合并方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • Vue 权限控制的两种方法(路由验证)

    Vue 权限控制的两种方法(路由验证)

    这篇文章主要介绍了Vue 权限控制的两种方法(路由验证),每种方法给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • 详解Vue中的基本语法和常用指令

    详解Vue中的基本语法和常用指令

    Vue.js 是一套构建用户界面的框架,**只关注视图层**,它不仅易于上手,还便于与第三方库或既有项目整合。这篇文章主要介绍了vue 的基本语法和常用指令,需要的朋友可以参考下
    2019-07-07
  • Vue组件更新数据v-model不生效的解决

    Vue组件更新数据v-model不生效的解决

    这篇文章主要介绍了Vue组件更新数据v-model不生效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • vue从零实现一个消息通知组件的方法详解

    vue从零实现一个消息通知组件的方法详解

    这篇文章主要介绍了vue从零实现一个消息通知组件的方法,结合实例形式分析了vue实现消息通知组件的具体原理、实现步骤、与相关操作技巧,需要的朋友可以参考下
    2020-03-03
  • element el-upload文件上传覆盖第一个文件的实现

    element el-upload文件上传覆盖第一个文件的实现

    这篇文章主要介绍了element el-upload文件上传覆盖第一个文件的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03

最新评论