Vue源码学习之初始化模块init.js解析

针对“Vue源码学习之初始化模块init.js解析”的完整攻略,我将从以下几个方面进行详细讲解。

标题

本文将重点讲解Vue源码中的init.js文件,即Vue实例的初始化模块,其中包含了Vue实例在创建过程中的各种初始化操作。

代码示例

首先,让我们来看一下init.js中的代码示例:

export function initState (vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}

这段代码主要是Vue实例初始化的入口,其中包含了初始化props、methods、data、computed和watch等操作。下面我们将对这些操作进行详细讲解。

初始化props

在init.js中,通过initProps方法来初始化props:

function initProps (vm: Component, propsOptions: Object) {
  const propsData = vm.$options.propsData || {}
  const props = vm._props = {}
  // cache prop keys so that future props updates can iterate using Array
  // instead of dynamic object key enumeration.
  const keys = vm.$options._propKeys = []
  const isRoot = !vm.$parent
  // root instance props should be converted
  observerState.shouldConvert = isRoot
  for (const key in propsOptions) {
    keys.push(key)
    const value = validateProp(key, propsOptions, propsData, vm)
    /* istanbul ignore else */
    if (process.env.NODE_ENV !== 'production') {
      const hyphenatedKey = hyphenate(key)
      if (isReservedAttribute(hyphenatedKey) ||
          config.isReservedAttr(hyphenatedKey)) {
        warn(
          `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`,
          vm
        )
      }
      defineReactive(props, key, value, () => {
        if (!isRoot && !isUpdatingChildComponent) {
          warn(
            `Avoid mutating a prop directly since the value will be ` +
            `overwritten whenever the parent component re-renders. ` +
            `Instead, use a data or computed property based on the prop's ` +
            `value. Prop being mutated: "${key}"`,
            vm
          )
        }
      })
    } else {
      defineReactive(props, key, value)
    }
    // static props are already proxied on the component's prototype
    // during Vue.extend(). We only need to proxy props defined at
    // instantiation here.
    if (!(key in vm)) {
      proxy(vm, `_props`, key)
    }
  }
  observerState.shouldConvert = true
}

在这段代码中,通过for循环遍历propsOptions,调用validateProp方法来验证prop值的正确性,并使用defineReactive方法将vm._props对象中的每个prop属性变成响应式的。

初始化data

接着,在initData方法中,初始化data:

function initData (vm: Component) {
  let data = vm.$options.data
  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {}
  if (!isPlainObject(data)) {
    data = {}
    process.env.NODE_ENV !== 'production' && warn(
      'data functions should return an object:\n' +
      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
      vm
    )
  }
  // proxy data on instance
  const keys = Object.keys(data)
  const props = vm.$options.props
  const methods = vm.$options.methods
  let i = keys.length
  while (i--) {
    const key = keys[i]
    if (process.env.NODE_ENV !== 'production') {
      if (methods && hasOwn(methods, key)) {
        warn(
          `Method "${key}" has already been defined as a data property.`,
          vm
        )
      }
    }
    if (props && hasOwn(props, key)) {
      process.env.NODE_ENV !== 'production' && warn(
        `The data property "${key}" is already declared as a prop. ` +
        `Use prop default value instead.`,
        vm
      )
    } else if (!isReserved(key)) {
      proxy(vm, `_data`, key)
    }
  }
  // observe data
  observe(data, true /* asRootData */)
}

在这段代码中,Vue通过getData方法获取data的值,并使用defineReactive方法将其变成响应式的。而后,再通过Object.keys(data)来遍历data,对其中的每个key值使用proxy方法,将其代理到vm实例上。最后,Vue调用observe方法来将整个data对象变为响应式的。

其他初始化操作

除了上述的props和data,还有methods、computed和watch等数据也都会通过Vue的init.js文件进行初始化。这些操作的实现原理跟上述两个类似,都需要使用Vue的一些核心方法来对相关数据进行响应式处理。

示例说明

为了让大家更好地理解以上内容,我将结合两个示例来进行说明:

  1. props示例

假设我们有这么一个Vue组件:

<template>
  <div>{{name}}</div>
</template>

<script>
  export default {
    name: 'child-component',
    props: ['name']
  }
</script>

这里组件定义了一个props属性name,我们可以在父组件中传入相应的值:

<child-component :name="'Tom'"></child-component>

通过Vue的initProps方法,Vue会对传入的props值进行验证,并让其变成响应式的。然后,我们在子组件中就可以访问this.name的值了。

  1. data示例

再来看一个表示当前时间的Vue组件:

<template>
  <div>{{currentTime}}</div>
</template>

<script>
  export default {
    data () {
      return {
        currentTime: new Date().getTime()
      }
    }
  }
</script>

在这个组件中,我们定义了一个初始值为当前时间的data属性currentTime。这个值将通过Vue的initData方法来实现响应式。

随着时间的推移,currentTime会不断更新,但因为在修改前currentTime已经通过defineReactive方法变成了响应式的,所以此时Vue会在组件内部触发相关的生命周期函数和更新操作,从而保证currentTime的值及时地更新到组件的视图中。

结束语

以上是针对“Vue源码学习之初始化模块init.js解析”的完整攻略,希望能帮助到你理解Vue源码中的初始化过程。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue源码学习之初始化模块init.js解析 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • 项目中一键添加husky实现详解

    下面是项目中一键添加Husky实现的完整攻略示例,分为如下几个步骤: 步骤一:初始化项目 首先,我们需要创建一个新项目并初始化它。我们可以通过以下命令创建并初始化一个名为“my-project”的新项目。 mkdir my-project cd my-project npm init -y 这个命令会创建一个名为“my-project”的文件夹,并初始化一个…

    Vue 2023年5月28日
    00
  • Vue实现倒计时小功能

    Vue实现倒计时小功能的完整攻略 在Vue中实现倒计时小功能需要以下几个步骤: 引入Vue组件和相关依赖:首先我们需要在标签中引入Vue.js的相关文件。 <head> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script&gt…

    Vue 2023年5月29日
    00
  • Vue.js中使用iView日期选择器并设置开始时间结束时间校验功能

    下面是详细的“Vue.js中使用iView日期选择器并设置开始时间结束时间校验功能”的攻略: 1. 安装iView 要使用iView日期选择器,首先需要在Vue.js项目中安装iView UI库。可以使用npm进行安装: npm install iview –save 安装完成后,在Vue.js项目的main.js文件中引入: import iView f…

    Vue 2023年5月28日
    00
  • Vue如何配置根目录@(引用路径)

    配置webpack配置文件 在使用Vue项目时,通常会由webpack进行构建,因此我们需要在webpack配置文件中进行根目录的配置。打开webpack配置文件,在module.exports对象下添加resolve属性,并在里面添加一个alias对象,指定根目录别名和实际路径,如下所示: module.exports = { // … resolve…

    Vue 2023年5月28日
    00
  • 使用webpack搭建vue项目及注意事项

    使用webpack搭建vue项目及注意事项 一、前言Vue.js 是前端非常流行的一种渐进式JavaScript框架,封装了响应式数据绑定、虚拟DOM、组件化等功能。而Webpack是最流行的前端代码模块化打包工具之一,可以根据不同需求配置不同的loader、plugin来编译打包代码,是现代前端工作流中很重要的部分。下面我们就来一步一步地学习使用Webpa…

    Vue 2023年5月28日
    00
  • 从vue源码解析Vue.set()和this.$set()

    从 Vue 源码解析 Vue.set() 和 this.$set() 在 Vue 中,我们使用 Vue.set() 或 this.$set() 来设置响应式对象的新属性或更新已有属性。这个方法的底层实现原理比较复杂,本文将从源码角度解析其底层实现过程。 Vue.set() 和 this.$set() 概述 在 Vue.js 中,我们可以使用 Vue.set(…

    Vue 2023年5月27日
    00
  • vue一步到位的实现动态路由

    实现动态路由的过程中,我们需要完成以下几个步骤: 定义路由表 动态注册路由 处理404页面 下面我们就来具体分析一下这三个步骤。 步骤一:定义路由表 我们首先需要定义一个路由表,其中包含了所有的页面路径以及对应的组件,它可以在一个独立的模块中定义。以一个示例项目为例,我们可以定义一个 routes 文件,如下: export default [ { path…

    Vue 2023年5月27日
    00
  • vue cli实现项目登陆页面流程详解

    下面是“Vue CLI实现项目登录页面流程详解”的完整攻略: 准备工作 首先,安装 Vue CLI,可以通过 npm 命令在终端进行安装: npm install -g @vue/cli 安装完成后,通过 Vue CLI 创建一个新项目: vue create my-project 然后,进入项目目录并启动项目: cd my-project npm run …

    Vue 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部