vue原理分析(七)研究new Vue()中的mergeOptions

news2025/1/15 15:20:27

今天我们来分析使用new Vue()中的mergeOptions

在Vue.prototype._init中有这么一段

if (options && options._isComponent) {

    // optimize internal component instantiation

    // since dynamic options merging is pretty slow, and none of the

    // internal component options needs special treatment.

    initInternalComponent(vm, options);

}

else {

    vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor), options || {}, vm);

}

这里用了mergeOptions()

找到这里用了mergeOptions代码f

unction mergeOptions(parent, child, vm) {

  {

      checkComponents(child);

  }

  if (isFunction(child)) {

      // @ts-expect-error

      child = child.options;

  }

  normalizeProps(child, vm);

  normalizeInject(child, vm);

  normalizeDirectives$1(child);

  // Apply extends and mixins on the child options,

  // but only if it is a raw options object that isn't

  // the result of another mergeOptions call.

  // Only merged options has the _base property.

  if (!child._base) {

      if (child.extends) {

          parent = mergeOptions(parent, child.extends, vm);

      }

      if (child.mixins) {

          for (let i = 0, l = child.mixins.length; i < l; i++) {

              parent = mergeOptions(parent, child.mixins[i], vm);

          }

      }

  }

  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;

}

接下来,我们逐步分析代码

1. checkComponents检查components 中的组件名是否规范

function mergeOptions(parent, child, vm) {

  {

      checkComponents(child);

  }

  ......

}

我们去找下checkComponents代码

function checkComponents(options) {

    for (const key in options.components) {

        validateComponentName(key);

    }

}

在checkComponents中,用for in 循环options.components,调用validateComponentName

function validateComponentName(name) {

    if (!new RegExp(`^[a-zA-Z][\\-\\.0-9_${unicodeRegExp.source}]*$`).test(name)) {

        warn$2('Invalid component name: "' +

            name +

            '". Component names ' +

            'should conform to valid custom element name in html5 specification.');

    }

    if (isBuiltInTag(name) || config.isReservedTag(name)) {

        warn$2('Do not use built-in or reserved HTML elements as component ' +

            'id: ' +

            name);

    }

}

如果组件名称未通过正则判断,则会有警告提示

2. 对入参child进行类型判断

function mergeOptions(parent, child, vm) {

  ......

  if (isFunction(child)) {

      // @ts-expect-error

      child = child.options;

  }

  ......

}

类型判断,如果child是个方法,则child = child.options;

3. 对props、inject、directives 进行标准化

unction mergeOptions(parent, child, vm) {

  ......

  normalizeProps(child, vm);

  normalizeInject(child, vm);

  normalizeDirectives$1(child);

  ......

}

这三个函数所做的事情很简单,就是将 options 中配置的 props、inject、directives 进行标准化

举个例子

props: ['age']

标准化下为

props: {

  age: {

    type: Number,

    default: 0,

    required: true,

    validator: function (value) {

      return value >= 0

    }

  }

}
inject: ['foo']

标准化下为

inject: {

  foo: {

    from: 'bar',

    default: () => [1, 2, 3]

  }

}

directives 的函数简写形式转换成对象形式

directives: {

  'color-swatch': function (el, binding) {

    el.style.backgroundColor = binding.value

  }

}

标准化位

directives: {

  'color-swatch': {

    bind: function (el, binding) {

      el.style.backgroundColor = binding.value

    },

    update: function (el, binding) {

      el.style.backgroundColor = binding.value

    }

  }

}

4. extends 和 mixins 选项的处理

function mergeOptions(parent, child, vm) {

  ......

  //在子选项上应用extends和mixins;

  //但只有当它是一个原始的选项对象

  //另一个mergeOptions调用的结果。

  //只有合并选项才有_base属性。

  // 注意,这里是个递归调用!!!

  if (!child._base) {

      // 配置选项中可以使用 extends 配置项,如果使用了该配置项的话,底层则递归调用 mergeOptions 方法,

      // 对 parent 和 extendsFrom 中的配置项进行合并

      if (child.extends) {

          parent = mergeOptions(parent, child.extends, vm);

      }

      // 配置选项中可以使用 mixins 配置项,如果使用了该配置项的话,底层则递归调用 mergeOptions 方法,

      // 对 parent 和 child.mixins[i] 中的配置项进行合并

      if (child.mixins) {

          for (let i = 0, l = child.mixins.length; i < l; i++) {

              parent = mergeOptions(parent, child.mixins[i], vm);

          }

      }

  }

  ......

}

5. 开始真正的合并处理

function mergeOptions(parent, child, vm) {

  ......

  const options = {};

  let key;

  for (key in parent) {

      mergeField(key);

  }

  for (key in child) {

      // 如果当前遍历的 key 在 parent 中不存在的话,再执行 mergeField(key)

      if (!hasOwn(parent, key)) {

          mergeField(key);

      }

  }

  // 用于合并某一个 key 的方法

  function mergeField(key) {

      // strats 是指合并策略集

      // strat 是指特定选项的合并策略,是一个函数

      const strat = strats[key] || defaultStrat;

      // 使用这个合并策略对 parent 和 child 中指定的 key 进行合并

      options[key] = strat(parent[key], child[key], vm, key);

  }

  return options;

}

首先创建一个 options 对象,这个对象就是最终返回的合并对象。

接下来遍历 parent options 对象,以遍历到的 key 作为参数执行 mergeField 方法,这样的话,parent options 对象中的所有 key 都已经处理到 options 对象中了

然后遍历 child options 对象,这一遍遍历是为了处理 child options 对象中独有的 key,内部的处理也是以 key 作为参数执行 mergeField 方法。

这里再研究下 const strat = strats[key] || defaultStrat;

该方法的作用是:用于合并 parent options 和 child options 对象中某一个 key。

在 Vue 中,不同的配置项有不同的合并策略,这些合并策略都存储在 strats 对象中,strats 对象的数据结构如下所示:

strats = {

  data: function(){},

  watch: function(){},

  props: function(){},

  methods: function(){},

  created: function(){},

  mounted: function(){},

  ......

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2119642.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【每日刷题】Day115

【每日刷题】Day115 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. LCR 089. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 2. LCR 090. 打家劫舍 II - 力扣&…

阿里云服务器镜像,有大用处

大家好&#xff0c;我是小悟 有时候阿里云旧服务器快到期了&#xff0c;想把项目、数据、软件挪到新服务器上&#xff0c;如果全部重新搭建的话&#xff0c;那无疑是耗时又费力。有了镜像迁移&#xff0c;就方便了许多。 新旧服务器的类型要一致&#xff0c;比如都是ECS服务器…

Matlab程序练习

Part1 1.求 [100,999] 之间能被 21整除的数的个数。 程序&#xff1a; 主文件&#xff1a;main.m clear; start_num 100; end_num 999; div_num 21; res div(start_num,end_num,div_num); fprintf("[%d,%d]之间能被%d整除的数的个数为%d个\n",start_num,end_…

使用Azure+C#+visual studio开发图像目标检测系统

在这篇文章里面&#xff0c;我们讲解使用AzureC#visual studio在Azure上做图像的目标检测系统。 笔者是头一次接触C#。之前以Python Java和Scala为主。感觉C#.Net是一种挺好用的开发系统。C#和Java非常像。会一个学另一个很快。 首先&#xff0c;目标检测是个什么东西&#x…

vulhub spring 远程命令执行漏洞(CVE-2022-22963)

1.执行以下命令启动靶场环境并在浏览器访问 cd spring/CVE-2022-22963docker-compose up -ddocker ps 2.反弹shell 构造payload 3.页面刷新抓包&#xff0c;修改内容 POST /functionRouter HTTP/1.1 Host: 172.16.1.89:8080 Accept-Encoding: gzip, deflate Accept: */* Acc…

任务栏颜色怎么改?快速实现Windows系统任务栏透明,全面指南和操作实践!

任务栏是电脑操作系统的重要组成部分&#xff0c;电脑会自动为任务栏选择颜色&#xff0c;一般分为浅色&#xff08;白色&#xff09;、深色&#xff08;黑色&#xff09;。如果想要设置成自己喜欢的颜色&#xff0c;也是可以更改的&#xff0c;那么任务栏颜色怎么改呢&#xf…

实时图像处理的加速器:《基于FPGA的数字图像处理原理及应用》(可下载)

图像处理技术已成为我们生活中不可或缺的一部分。从智能手机的摄像头到卫星图像分析&#xff0c;从医疗影像到安全监控&#xff0c;图像处理技术的应用无处不在。随着技术的进步&#xff0c;我们对图像处理的速度和质量要求也越来越高。在这一背景下&#xff0c;现场可编程门阵…

CDGA|大模型数据治理的案例与实践深入剖析

随着人工智能技术的飞速发展&#xff0c;大模型在数据治理领域的应用日益广泛&#xff0c;为企业带来了前所未有的机遇与挑战。本文将通过几个具体案例&#xff0c;深入剖析大模型在数据治理中的实践应用&#xff0c;探讨其带来的变革与影响。 大模型在数据治理中的核心优势 大…

大腾智能出席龙华云创中心启动与鸿蒙园揭牌仪式

在数字化转型的浪潮中&#xff0c;深圳市龙华区再次引领行业创新&#xff0c;携手华为云成功举办“龙华工业软件云工程应用创新中心启动仪式暨鸿蒙产业园揭牌仪式”&#xff0c;本次盛会已于8月26日圆满落幕。活动现场&#xff0c;来自全国各地的行业精英、企业领袖及专家学者汇…

资料分析(2)

C B 增长量不变就是1002020 上面是利滚利:按照20%当利息 本题:涨跌幅度的意思就是增长率&#xff0c;本题是按照增长率不变的情况下进行计算D B 7551400X>1.2*100000 B B B 总体增量部分增量之和 先进行计算固定通信业务收入的增长量移动通信业务实现收入的增长量 增长量现期…

11大排序的原理讲解和Python源码剖析

排序算法 【谁教你这么剪的 | 11大排序的原理讲解和Python源码剖析】 https://www.bilibili.com/video/BV1Zs4y1X7mN/?share_sourcecopy_web&vd_sourceed4a51d52f6e5c9a2cb7def6fa64ad6a 稳定&#xff1a;如果a原本在b前面&#xff0c;而ab&#xff0c;排序之后a仍然在b…

如何实现数字孪生?看这篇就够了

数字孪生&#xff08;Digital Twin&#xff09;是一种集成了物理世界和数字世界的先进概念&#xff0c;通过高精度的模拟来反映现实世界的实体或系统。它利用物联网&#xff08;IoT&#xff09;、大数据、人工智能&#xff08;AI&#xff09;、云计算等先进技术&#xff0c;实现…

应对AI挑战的职业发展与培训策略

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;各行各业正经历着前所未有的变革。为了在这场变革中保持竞争力并实现个人职业发展&#xff0c;职场人士需要积极应对AI带来的挑战&#xff0c;通过制定有效的职业发展与培训策略来不断提升自我。以下是几个关…

大数据决策分析平台建设方案(可编辑的56页PPT)

引言&#xff1a;在当今信息爆炸的时代&#xff0c;大数据已成为企业决策制定、业务优化与市场洞察的重要驱动力。为了充分挖掘大数据的潜在价值&#xff0c;提升决策效率与精准度&#xff0c;构建一套高效、灵活、可扩展的大数据决策分析平台显得尤为重要。通过大数据分析平台…

佰朔资本:沪指跌0.23%,金融板块集体上扬,半导体等板块下挫

6日早盘&#xff0c;沪指盘中轰动回落&#xff0c;深证成指、创业板指弱势下探&#xff0c;上证50指数逆市上扬&#xff0c;场内超4400股飘绿。 到午间收盘&#xff0c;沪指跌0.23%报2782点&#xff0c;深证成指跌1.01%&#xff0c;创业板指跌1.29%&#xff0c;上证50指数微涨…

不小心删除丢失了所有短信?如何在 iPhone 上查找和恢复误删除的短信

不小心删除了一条短信&#xff0c;或者丢失了所有短信&#xff1f;希望还未破灭&#xff0c;下面介绍如何在 iPhone 上查找和恢复已删除的短信。 短信通常都是非正式和无关紧要的&#xff0c;但短信中可能包含非常重要的信息。因此&#xff0c;如果您删除了一些短信以清理 iPh…

LeetCode第414场周赛(第一题)

目录 一&#xff1a;题目&#xff1a;3280. 将日期转换为二进制表示 一&#xff1a;题目&#xff1a;3280. 将日期转换为二进制表示 给你一个字符串 date&#xff0c;它的格式为 yyyy-mm-dd&#xff0c;表示一个公历日期。 date 可以重写为二进制表示&#xff0c;只需要将年…

idea创建一个spring项目,并编写一个初级spring项目实战(全网最详细)

1.创建spring项目 创建后界面显示 2.再pom.xml文件中添加Spring框架依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.10</version> </dependency> 注意&…

Spring中FactoryBean的高级用法实战

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

AT3340-6T杭州中科微BDS定位授时板卡性能指标

AT3340-6T是一款高性能多系统卫星定位安全授时板卡&#xff0c;可通过配置支持各个单系统的定位授时。 外观尺寸&#xff1a; 电气参数 应用领域&#xff1a; 通信基站授时 电力授时 广播电视授时 轨道系统授时 金融系统授时 其他授时应用 注意事项&#xff1a; 为了充分发挥…