vue初始化data方法有哪些

来源:php中文网 | 2022-12-26 18:04:54 |

本教程操作环境:windows7系统、vue3版,DELL G3电脑。

vue data有两种初始化的方式,function和object,但是这两种情况适用场景有哪些?能不能通用?带着这两个问题咱们一起分析下

data初始化


(资料图片)

// 代码来源于官网示例// 第一种定义方式var data = { a: 1 }// 直接创建一个实例var vm = new Vue({  data: data})// Vue.extend() 中 data 必须是函数var Component = Vue.extend({// 第二种定义方式  data: function () {    return { a: 1 }  }})

上述代码简单描述了data定义的两种方式

function

object

官网demo中也着重说了extend中data初始化不能用object。那么为什么呢?

源码分析

按照官网demo,Vue.extend中的data初始化不能是Object,如果我们强制写成Object会出现什么?

var Component = Vue.extend({  data: { a: 1 }})

运行以后chrome的consolo直接报错,信息如下

vue.esm.js?efeb:591 [Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.

通过分析源码以及报错信息,当触发Vue.extend的时候,他会做一个合并操作,把一个基础组件(里面vmode, transtion等)和你定义在extend内的信息,通过mergeField往options上合并,当合并到data的时候,他会触发strats.data,在这个里面会check data是不是一个function,这里需要注意的是filter、components等和data走的是两套合并流程,详细的请看代码注释,如下

// vue.extend 源码地址https://github.com/vuejs/vue/blob/dev/src/core/global-api/extend.js  Vue.extend = function (extendOptions: Object): Function {  ...  // 在这里会触发mergeOptions方法  Sub.options = mergeOptions(      Super.options,      extendOptions    )  ...}// mergeOptions 源码地址https://github.com/vuejs/vue/blob/dev/src/core/util/options.jsexport function mergeOptions (  parent: Object,  child: Object,  vm?: Component): Object {  ...  const options = {}  let key  // parent对象内包含components、filter,、directive  for (key in parent) {    mergeField(key)  }  // child对象内对应的是Vue.extend内定义的参数  for (key in child) {    if (!hasOwn(parent, key)) {      mergeField(key)    }  }  function mergeField (key) {  // 这一步是根据传入的key找到不同的合并策略filter、components、directives用到合并策略是这个方法mergeAssets和data用到的不一样,当合并到data的时候会进入专属的合并策略方法内    const strat = strats[key] || defaultStrat    options[key] = strat(parent[key], child[key], vm, key)  }}// strats.data  源码地址https://github.com/vuejs/vue/blob/dev/src/core/util/options.jsstrats.data = function (  parentVal,  childVal,  vm) {  if (!vm) {  // 如果data不是function的话会直接走下面的报错信息    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)};

其他情况

其实我们上述代码只是一个简单的流程,在实际开发中同类情况有:子组件内、路由内都不可以把data定义为一个对象,因为他们底层都调用了mergeOptions方法

什么时候可以定义成一个对象

在vue初始化的时候,如下

new Vue({  data: {    linke: "//sinker.club"  }})

意义

ok,上面说了那么多,那么这么做的意义是什么?为什么那几种情况不可以定义为对象?其实回答这个问题,需要回到js本身,众所周知js数据类型分为引用和基本,引用类型包含Object, Array, Function,何为引用类型就不在这里阐述了

var obj = {link: "//www.sinker.club"}  var obj2 = obj  var obj3 = obj  obj2.link = "//gitlab.sinker.club"  console.log(obj3.link) // "//gitlab.sinker.club"

上述代码反应了一个问题,由于obj3和obj2在内存中都是指向一个地址,那么obj2的修改会影响到obj3,当然处理这种问题可以用深copy来做到

JSON.parse(JSON.stringify(obj))

deepClone(obj)

但是这两种做法需要开发或者框架每一次都要深copy一次,当数据量大的时候对性能什么都不友好,那么Vue怎么做的呢?把data定义成一个function

function data() {  return {   link: "//sinker.club"  }}var obj = test()var obj2 = test()obj2.link ="//gitlab.sinker.club"console.log(obj.link) "//sinker.club"

为什么这么做?解决的场景是什么呢?

比如我定一个子组件,data是按照对象的方式定义的,这个组件在多个地方引用,如果其中一个引用此组件的data修改了,那么就会造成其余引用此组件的data同时改变, end.

扩展知识:

vue实例的时候定义data属性既可以是一个对象,也可以是一个函数

const app = new Vue({    el:"#app",    // 对象格式    data:{        foo:"foo"    },    // 函数格式    data(){        return {             foo:"foo"        }    }})

组件中定义data属性,只能是一个函数

如果为组件data直接定义为一个对象

Vue.component("component1",{    template:`<div>组件</div>`,    data:{        foo:"foo"    }})

则会得到警告信息

说明:

vue中组件是用来复用的,为了防止data复用,将其定义为函数。

vue组件中的data数据都应该是相互隔离,互不影响的,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响,就需要通过data函数返回一个对象作为组件的状态。

当我们将组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,拥有自己的作用域,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。

当我们组件的date单纯的写成对象形式,这些实例用的是同一个构造函数,由于JavaScript的特性所导致,所有的组件实例共用了一个data,就会造成一个变了全都会变的结果。

以上就是vue初始化data方法有哪些的详细内容,更多请关注php中文网其它相关文章!

关键词: vue3