vue2源码解读笔记(一)

Vue源码系列(一):Vue源码解读的正确姿势 作为一名开发人员,阅读源码是非常好的学习方式,尤其Vue又是当下很受欢迎的前端框架,随着用的人越来越多,不断推动着源码地完善。在源码中有着各位大佬多年积淀下来的精华,而这些精华就非常值得我们学习。 阅读详情

前言

第一,这篇文章比较长,需要占用你比较多时间,请使用一整段时间阅读和实践本文
第二,内容是作者代码断点+源码阅读+资料查阅核实的产出,有笔误和理解错误的地方欢迎指证

  • 阅读本文的背景:当你前端的学习到了一个瓶颈
  • 阅读目的:本文阅读目的:学会调试vue框架源码,读懂vue源码的init部分,理解vue的设计方式,从而提升技术深度

前置条件

  • js基础扎实
  • es6语法和特性熟悉
  • 代码的设计模式有一定了解
  • flow语法有基本了解

在开始之前,有必要学习一下 VUE 源码中用到的 flow
这里提供一个中文翻译的文档网站。参考:https://zhenyong.github.io/flowtype/docs/five-simple-examples.html#_

一、源码下载

源码下载,调试见歹佬原文:https://juejin.cn/post/6949370458793836580
(可以直接看这个歹佬的系列原文,不止技术厉害,文章也写得好。我这里是个人学习的笔记,可能你也遇到了,可以参考)
项目目录如下:
image.png

二、断点调试

在 /examples 目录下增加一个示例文件 —— test.html,在文件中添加如下内容:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue 源码解读</title>
</head>
<body>
  <div id="app">
    {{ msg }}
  </div>
  <script src="../dist/vue.js"></script>
  <script>
    debugger
    new Vue({
      el: '#app',
      data: {
        msg: 'hello vue'
      }
    })
  </script>
</body>
</html>

在浏览器中打开控制台,然后打开 test.html,则会进入断点调试,然后找到 Vue 构造函数所在的文件
tip:怎么找到断点对应的文件?如下如右击选Reveal in sidebar,再右侧能看到文件名
截屏2022-01-21 下午5.36.38.png

三、Vue 初始化过程

0、下一步里的options由来

src/core/global-api/index.js

/* @flow */
import { ASSET_TYPES } from 'shared/constants'
……
export function initGlobalAPI (Vue: GlobalAPI) {
  ……
  Vue.options = Object.create(null)
  ASSET_TYPES.forEach(type => {
    Vue.options[type + 's'] = Object.create(null)
  })

  // this is used to identify the "base" constructor to extend all plain-object
  // components with in Weex's multi-instance scenarios.
  Vue.options._base = Vue

  extend(Vue.options.components, builtInComponents)

  initUse(Vue)
  initMixin(Vue)
  initExtend(Vue)
  initAssetRegisters(Vue)
}
1、Vue 构造函数在 /src/core/instance/index.js 文件中
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
// Vue的构造函数,类,所以首字母大写
function Vue (options) {
	// 判断环境 和 实例(instanceof是判断前面的对象,是否是后面对象(类)的实例。不是判断是否是父类)
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
  	// 不是就预警,需要用new 来实例化类
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  //定义 Vue.prototype._init 方法
  this._init(options)
}

initMixin(Vue) // 定义上面_ini方法的js
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

export default Vue
2、this._init(options)的实现,/src/core/instance/init.js
/* @flow */

import config from '../config'
import { initProxy } from './proxy'
import { initState } from './state'
import { initRender } from './render'
import { initEvents } from './events'
import { mark, measure } from '../util/perf'
import { initLifecycle, callHook } from './lifecycle'
import { initProvide, initInjections } from './inject'
import { extend, mergeOptions, formatComponentName } from '../util/index'

let uid = 0

// 静态检查参考flow.js
// Vue入参变变量名,Class是类类型,<Component>范型指定Component(什么是范型的作用可以参考ts的:https://www.tslang.cn/docs/handbook/generics.html)
export function initMixin (Vue: Class<Component>) {
  // 负责 Vue 的初始化过程 (:?的意思是,入参有一个或没有,有则是Object类型)
  Vue.prototype._init = function (options?: Object) {
    // 这里开始建议打断点一步步看。vue实例就是this,内容是:$data: undefined,$isServer: false,$props: undefined,$ssrContext: undefined

    const vm: Component = this
    // 每个 vue 实例都有一个 _uid,并且是依次递增的
    vm._uid = uid++

	// 下面这段代码主要是用来测试代码性能的,在这个时候相当于打了一个"标记点"来测试性能。
	// window.performance用法参考:https://segmentfault.com/a/1190000014479800
	// vue源码声明使用位置:src/core/util/perf.js,学习performance API多掌握一个靠谱的js代码性能测试方式
    let startTag, endTag
    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      startTag = `vue-perf-start:${vm._uid}`
      endTag = `vue-perf-end:${vm._uid}`
      mark(startTag)
    }

    // a flag to avoid this being observed
    // 在其它js逻辑里使用。如果传入值的_isVue为ture时(即传入的值是Vue实例本身)不会新建observer实例(这里可以暂时理解新建observer实例就是让数据响应式)。
    vm._isVue = true
    // merge options
    // 符合第一个条件是,即当前这个Vue实例是组件
    if (options && options._isComponent) {
      //优化内部组件实例化
	  //因为动态选项合并非常慢,而且
	  //内部组件选项需要特殊处理。
      initInternalComponent(vm, options)
    } else {
       // 符合第二个条件时,即当前Vue实例不是组件。而是实例化Vue对象
       /**
       * 合并 Vue 的全局配置到根组件的局部配置,比如 Vue.component 注册的全局组件会合并到 根实例的 components 选项中
       * 至于每个子组件的选项合并则发生在两个地方:
       *   1、Vue.component 方法注册的全局组件在注册时做了选项合并
       *   2、{ components: { xx } } 方式注册的局部组件在执行编译器生成的 render 函数时做了选项合并,包括根组件中的 components 配置
       */
       // 合并两个选项,出现相同配置项时,子选项会覆盖父选项的配置
       //  mergeOptions在util/options.js,建议看一下
      vm.$options = mergeOptions(
        // 具体实现在同文件的下方,这里作省略
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }
    /* istanbul ignore else */
    // 判断环境,开发环境直接赋值。生产环境在initProxy内判断是否可以使用porxy(ES6特性),可以则使用,不行则和else一样的处理
    // 所以说vue2其实没用到porxy代理是不准确的,代码内会根据是否环境支持来使用
    // 补充判断是否可用proxy:typeof Proxy !== 'undefined' &&  typeof Proxy === 'function' && /native code/.test(Proxy.toString())
    if (process.env.NODE_ENV !== 'production') {
      initProxy(vm)
    } else {
      vm._renderProxy = vm
    }
    // expose real self
    vm._self = vm
    // 初始化组件实例关系属性,比如 $parent、$children、$root、$refs 等
    initLifecycle(vm)
    // 初始化自定义事件
    initEvents(vm)
    // 解析组件的插槽信息,得到 vm.$slot,处理渲染函数,得到 vm.$createElement 方法,即 h 函数
    initRender(vm)
    // 调用 beforeCreate 钩子函数
    callHook(vm, 'beforeCreate')
    // 初始化组件的 inject 配置项,得到 result[key] = val 形式的配置对象,然后对结果数据进行响应式处理,并代理每个 key 到 vm 实例
    initInjections(vm) // resolve injections before data/props
    // !! **数据响应式的重点**,处理 props、methods、data、computed、watch
    initState(vm)
    // 解析组件配置项上的 provide 对象,将其挂载到 vm._provided 属性上
    initProvide(vm) // resolve provide after data/props
    // 调用 created 钩子函数
    callHook(vm, 'created')

    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      vm._name = formatComponentName(vm, false)
      mark(endTag)
      measure(`vue ${vm._name} init`, startTag, endTag)
    }
	// 如果发现配置项上有 el 选项,则自动调用 $mount 方法,也就是说有了 el 选项,就不需要再手动调用 $mount,反之,没有 el 则必须手动调用 $mount
    if (vm.$options.el) {
      // 调用 $mount 方法,进入挂载阶段
      vm.$mount(vm.$options.el)
    }
  }
}
3、resolveConstructorOptions说明
export function resolveConstructorOptions (Ctor: Class<Component>) {
  let options = Ctor.options
  if (Ctor.super) {
    const superOptions = resolveConstructorOptions(Ctor.super)
    const cachedSuperOptions = Ctor.superOptions
    if (superOptions !== cachedSuperOptions) {
      // super option changed,
      // need to resolve new options.
      Ctor.superOptions = superOptions
      // check if there are any late-modified/attached options (#4976)
      const modifiedOptions = resolveModifiedOptions(Ctor)
      // update base extend options
      if (modifiedOptions) {
        extend(Ctor.extendOptions, modifiedOptions)
      }
      options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions)
      if (options.name) {
        options.components[options.name] = Ctor
      }
    }
  }
  return options
}

resolveConstructorOptions方法,从字面意思来看,这个方法是来解析constructor上的options属性的。
这个方法要分成两种情况来说明,第一种是Ctor是基础Vue构造器的情况,另一种是Ctor是通过Vue.extend方法扩展的情况。
第一种、当Ctor(Ctor其实就是构造函数)是基础Vue构造器时,就是通过new关键字来新建Vue构造函数的实例。这个时候options就是Vue构造函数上的options。如下图
image.png
第二种、如果Ctor是Vue.extend创建的"子类",例如下面的情况:

  var Profile = Vue.extend({
     template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>'
  })
  // Vue.mixin改变了"父类"options
  Vue.mixin({ data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
   }})
   new Profile().$mount('#example')

如果”自身“有新添加的options,则把新添加的options属性添加到Ctor.extendOptions属性上。调用mergeOptions方法合并"父类"构造器上的options和”自身“上的extendOptions,最后返回合并后的options。

4、initInjections说明

src/core/instance/inject.js

  • 初始化 inject 配置项
  • 1、得到 result[key] = val
  • 2、对结果数据进行响应式处理,代理每个 key 到 vm 实例
export function initInjections (vm: Component) {
  const result = resolveInject(vm.$options.inject, vm)
  if (result) {
    // 全局打标记的一个好方式,观察者模式,切换观察对象
    toggleObserving(false)
    Object.keys(result).forEach(key => {
      /* istanbul ignore else */
      if (process.env.NODE_ENV !== 'production') {
        defineReactive(vm, key, result[key], () => {
          warn(
            `Avoid mutating an injected value directly since the changes will be ` +
            `overwritten whenever the provided component re-renders. ` +
            `injection being mutated: "${key}"`,
            vm
          )
        })
      } else {
        defineReactive(vm, key, result[key])
      }
    })
    toggleObserving(true)
  }
}
// -----分割线-----
// 上述观察的实现,src/core/observer/index.js
export let shouldObserve: boolean = true
export function toggleObserving (value: boolean) {
  shouldObserve = value
}
5、resolveInject说明
// 解析 inject 配置项,从祖代组件的 provide 配置中找到 key 对应的值,否则用 默认值,最后得到 result[key] = val
export function resolveInject (inject: any, vm: Component): ?Object {
  if (inject) {
    // inject is :any because flow is not smart enough to figure out cached
    // 上述是源码注释,看着就有趣,静态检查是用的flow.js(vue2用的js),说人家不智能,所以只能选any类型
    // 这里用create方法创建了空的对象,Object.create(null)简单理解就是result的protype是null。具体理解参考这篇博客:https://www.jianshu.com/p/28d85bebe599
    const result = Object.create(null)
    // inject 配置项的所有的 key
    const keys = hasSymbol
      ? Reflect.ownKeys(inject)
      : Object.keys(inject)

    for (let i = 0; i < keys.length; i++) {
      const key = keys[i]
      // #6574 in case the inject object is observed...
      // continue的意思是,key === '__ob__'时,for循环内,continue下的代码不执行,执行下一次的循环。可以参考:https://blog.youkuaiyun.com/ll594317566/article/details/100692203
      // 这里continue用法可以参考和学习,等价于 if (key !== '__ob__') { ... // continue 跳过的代码 }
      if (key === '__ob__') continue
      // 拿到 provide 中对应的 key
      const provideKey = inject[key].from
      let source = vm
      // 遍历所有的祖代组件,直到 根组件,找到 provide 中对应 key 的值,最后得到 result[key] = provide[provideKey]
      while (source) {
        if (source._provided && hasOwn(source._provided, provideKey)) {
          result[key] = source._provided[provideKey]
          break
        }
        source = source.$parent
      }
      // 如果上一个循环未找到,则采用 inject[key].default,如果没有设置 default 值,则抛出错误
      if (!source) {
        if ('default' in inject[key]) {
          const provideDefault = inject[key].default
          result[key] = typeof provideDefault === 'function'
            ? provideDefault.call(vm)
            : provideDefault
        } else if (process.env.NODE_ENV !== 'production') {
          warn(`Injection "${key}" not found`, vm)
        }
      }
    }
    return result
  }
}

四、总结

Vue 的初始化过程(new Vue(options))都做了什么?

  • 处理组件配置项
  • 初始化根组件时进行了选项合并操作,将全局配置合并到根组件的局部配置上
  • 初始化每个子组件时做了一些性能优化,将组件配置对象上的一些深层次属性放到 vm.$options 选项中,以提高代码的执行效率
  • 初始化组件实例的关系属性,比如 parent、parent、parent、children、root、root、root、refs 等
  • 处理自定义事件
  • 调用 beforeCreate 钩子函数
  • 初始化组件的 inject 配置项,得到 ret[key] = val 形式的配置对象,然后对该配置对象进行浅层的响应式处理(只处理了对象第一层数据),并代理每个 key 到 vm 实例上
  • 数据响应式,处理 props、methods、data、computed、watch 等选项
  • 解析组件配置项上的 provide 对象,将其挂载到 vm._provided 属性上
  • 调用 created 钩子函数
  • 如果发现配置项上有 el 选项,则自动调用 $mount 方法,也就是说有了 el 选项,就不需要再手动调用 $mount 方法,反之,没提供 el 选项则必须调用 $mount
  • 接下来则进入挂载阶段
Vue源码解读(下)-vue2 主要是从原理、实战层面解读了Vue2版本的核心,本节接着分享Vue2源码内容,从底层源码解读Vue2,抽丝剥茧探究Vue2的框架结构,核心的响应式原理实现。 阅读详情

相关推荐

Vue 源码解读-学习方法

前言 最近在准备一些 Vue 系列的文章和视频,之前 Vue 的源码也读过好几遍,但是一直没写相关的文章,所以最近就计划写一写。 目标 精通 Vue 技术栈的源码原理,这是这系列的文章最终目的。 首先会从 Vue 源码解读开,会产出一系列的文章和视频,从详细刨析源码,再到手写 Vue 1.0和Vue 2.0。之后会产出周边生态相关库的源码分析和手写系列,比如:vuex、vue-router、vue-cli 等。 相信经过这一系列的认真学习,大家都可以在自己的简历上写上这么一条:精通...

LeZiJie的博客 1324

vue2源码解析(学习笔记)

vue源码调试解析

weixin_47454918的博客 3629

约2万字-Vue源码解读汇总篇(续更)

未完待续...Vue源码解读:06Vue3探索篇Vue源码解读:05生命周期篇Vue源码解读:04模板编译篇Vue源码解读:03虚拟Dom篇Vue源码解读:02变化侦测篇Vue源码解读:01核心思想篇Vue源码解读:前言篇从写下的代码,到用户见到界面,大致经历以下几个流程:模板字符串=》ast树=》render函数=》vnode=》用户见到的界面。将开发者写下的模板字符串,经过一些列处理,生成render函数的这一过程就是模板编译。简单地说,模板编译解析就是为了得到render函数。

布知什么 1881

vue2.x源码解析(一)

本文以vue2.x框架作为分析,简单记录整个源码编译的过程。

weixin_45514326的博客 2753

大前端进阶-读懂vuejs源码

前言 此文章适合准备第一次阅读vuejs源码的童鞋,由于vuejs的源码非常多,而且分布在各个文件夹中,因此想要读懂源码,需要理清整个框架的脉络。此文章就是从编译入口出发,找到源码中的关键点。 准备工作 打包源码 浏览器调试比单纯的阅读源码更有效率,那么如何为vuejs添加sourceMap? 1.fork vue源码仓库到自己的github仓库中,这样,可以随便添加注释和修改。 2.下载项目,打开package.json文件,找到文件中: 1.vuejs使用rollup打包,在dev命令最后添加--so

Arui_0的博客 528

Arduino智能小灯DIY:人体感应+光线感应+蓝牙控制全攻略(附完整代码)

本文提供了一份完整的Arduino智能小灯DIY制作指南。项目融合了人体感应、光线感应与蓝牙控制三大功能,通过详细的硬件清单、电路连接图、核心逻辑讲解及附带的完整代码,手把手教你打造一个能自动感知环境与人、并支持手机远程控制的智能照明装置,是入门智能家居和物联网开发的绝佳实践。

java5的博客 1094

Vue2源代码解读(含源码)

Vue2源代码解读(含源码)

weixin_43263566的博客 2867

svn co --depth和svn up --set-depth 只check out下一层文件 只更新指定文件 只更新下一层的用法

svn的工程可能很大 有时我们只需要部分文件即可 这里介绍几个命令 1.svn co(check out) --depth --depth=empty,files,immediates,infinity 假设某svn结构如下 svn://root/PRO/A_dir/a svn://root/PRO/B_dir/b svn://root/PRO/c_file svn co --depth=emptysvn://root/PRO 此时只会在本地check out出 PRO/的空目录。 sv.

cy413026的博客 1万+

vue2源码

方法是为传入的data对象属性添加getter和setter的。proxy()方法是将vm[key]代理到的。

qq_40745468的博客 761

ZYNQ程序固化实战:从BOOT.bin生成到QSPI/SD卡双启动模式详解

本文详细解析了ZYNQ 7000系列程序固化的完整流程,重点解决了程序断电丢失问题。通过实战演示,从生成BOOT.bin文件到配置QSPI与SD卡双启动模式,逐步指导开发者实现程序在外部存储中的永久驻留,确保产品脱离调试器独立运行。

weixin_29193259的博客 517

GD32F303 ADC+DMA实战:用硬件过采样搞定多通道数据采集(附完整代码)

本文详细介绍了GD32F303系列MCU通过ADC+DMA结合硬件过采样技术实现多通道数据采集的实战方案。从硬件设计要点到软件配置全解析,包括时钟树配置、ADC模块初始化和DMA传输设置,提供了完整的代码示例和优化技巧,帮助工程师构建高精度、低功耗的数据采集系统。

weixin_30466039的博客 319

Vue2源码解读

例如,Vue.js 会在内部定义一些工具方法,这些工具方法既可以在浏览器端的 Vue.js 中使用,也可以在服务端的 Vue.js 中使用。需要注意的是,在Vue 2.x中,如果你使用了构建时预编译(例如通过vue-loader),那么模板已经被编译成了渲染函数,Vue在运行时就不需要再次编译了。在Vue 3.x中,编译过程有所变化,因为Vue 3引入了编译时优化和更高效的编译策略,但基本概念仍然相同:模板被编译成渲染函数,然后Vue使用这些渲染函数来生成和更新DOM。时,实际上是在调用这个构造函数。

警警的博客 2475

STM32L476低功耗实战:LPTIM精准定时唤醒STOP2模式与系统级功耗优化

本文深入探讨了STM32L476低功耗实战技巧,重点解析了LPTIM精准定时唤醒STOP2模式的配置与优化。通过详细的步骤指南和实战经验分享,帮助开发者实现系统级功耗优化,特别适合电池供电设备开发。文章涵盖LPTIM1定时器配置、STOP2模式进入流程及常见问题排查,助力将整机功耗降至8.2uA级别。

weixin_33686714的博客 435

Vue源码解析(一)

前言:接触vue已经有一段时间了,前面也写了几篇关于vue全家桶的内容,感兴趣的小伙伴可以去看看,刚接触的时候就想去膜拜一下源码~可每次鼓起勇气去看vue源码的时候,当看到几万行代码的时候就直接望而却步了,小伙伴是不是也跟我当初一样呢? 下面分享一下我看vue源码的一些感触,然后记录一下我对源码的理解,欢迎指正,纯属个人笔记,大牛勿喷! 我们直接上一张vue官网的vue的生命周期图: 我们跟着源...

vv_bug 2万+

Python 爬虫实战:爬取 GitHub 热门项目(星数 / 语言 / 作者)

本文系统介绍了使用Python爬虫技术获取GitHub热门项目数据的完整方案。通过分析GitHub Trending页面和官方API两种数据源,详细讲解了HTML解析、JSON数据处理、反爬应对策略等关键技术。采用requests、BeautifulSoup、pandas等工具链,实现了项目信息(名称、星数、语言等)的结构化爬取,并配套数据清洗、统计分析及可视化功能。特别强调遵守GitHub API使用规范,包括Token认证、请求频率控制等合规要求。该方案为开发者提供了一种高效、合法的数据采集方法,适用于

2503_91057718的博客 2343

Pdu Router(PduR)模块

1. PduR路由基本功能 2. PduR总线网关功能 3. PduR缓存机制 4. 总结

weixin_43759043的博客 3849

vueJs源码解读0-1

vue源码解读-1 在github上下载到源码的后在src的目录下也即是该所有分块的源文件的地址所在的地方,使用webstrom在file–>Settings–>languages&Frameworks中选择javascript使用ECMAScript6 1. index.js import Vue from ‘./instance/vue’ import installGlobal

RankBill 4026

独立游戏之路:Tap篇 -- 个人开发者上架TapTap步骤和注意事项

作为一名游戏开发者,将自己的独立游戏上架到 TapTap 平台是一个不错的选择。TapTap 是一个拥有大量用户的游戏社区平台,上架游戏可以让更多的玩家发现和体验你的游戏。TapTap 是一个游戏社区平台,用户可以在平台上下载和分享游戏。TapTap 拥有大量的用户,并且用户活跃度高,这为独立游戏开发者提供了一个很好的展示和推广平台。进入TapTap开发者服务后台。

陈言必行 -- Unity游戏开发领域优质博主 6414

Vue源码解读

本文主要介绍了Vue.js的源代码解读相关的步骤和技巧,包括安装Vue.js源代码、学习Vue.js的架构、阅读Vue.js的源代码、参考Vue.js的文档和社区资源,以及尝试修改Vue.js的源代码等内容。如果你想深入学习Vue.js的实现原理和内部机制,阅读本文可以为你提供一定的参考和帮助。

m0_73442777的博客 2934

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

深入讲解一下 Vue 3 的核心源码库 vuejs/core

track 负责“依赖收集”,trigger 负责“派发更新”。

u011091936的博客 1392

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Vue2 源码解读一:Global API

文章目录Vue源码解读一:源码准备1、准备源码,添加调试2、Flow静态类型检查3、目录说明[Vue源码解读一:Global API](https://fanyi.baidu.com/#auto/zh/) Vue源码解读一:源码准备 1、准备源码,添加调试 下载Vue源码 Vue Release ; 安装依赖cnpm install,使用cnpm安装 修改package.json中的scripts,dev脚本添加--sourcemap,改为"dev": "rollup -w -c scripts/conf

Vincent的博客 1334

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

vueJs源码解读0-2

上篇文章已经对index.js中的基本调用情况做了说明,接下来的几篇将对各个函数做仔细的分析,能力有限,文章中不足之处,希望大家能够指正! 上篇中提到在instance/vue中使用了9个高阶函数来构建(install)Vue构造函数(并不会调用该构造函数的进行初始化的过程),一切等在使用new Vue({….})的时候将一个全新的对象作为函数内this的值,返回该新对象作为结果(函数 调用中

RankBill 1万+

Vue源码解读(上)-vue2

MVVM,全称“Model-View-ViewModel”,最早于2005年由微软架构师 JohnGossman 提出,MVVM是一种软件的设计/架构模式,这种架构模式在前端混合App开发中得到了广泛的应用;Model顾名思义是模型,View是视图,ViewModel是MVVM模式的核心 => 视图模型,模型与视图之间并不能直接通信,而是通过中间人ViewModel视图模型产生联系。【Model】:模型,指后端传递的数据;【View】:视图,指用户所看到的页面;

享白 1227

Vue2 源码解读三:Vue实例

文章目录 Vue2 源码解读一:Global API Vue2 源码解读二:mergeOptions Vue2 源码解读三:new Vue   1、入口方法   2、initMixin   3、stateMixin   4、eventsMixin   5、lifecycleMixin   6、renderMixin Vue2 源码解读三:new Vue 在创建Vue应用时,都会用到初始化Vue实例对象的方法new Vue(options)。接下来,就看看在创建Vue实例对象时,Vue2源码都做了些..

Vincent的博客 625

探索VueJS核心:tiny-vue,你的源码学习伙伴

探索VueJS核心:tiny-vue,你的源码学习伙伴 项目简介 tiny-vue 是一个精心简化版的VueJS实现,专为初学者设计,帮助理解VueJS v1.0.28的核心概念。这个项目的创建者为了帮助那些在复杂源码中迷失方向的新手,将VueJS的核心功能拆解成更易于理解的部分,让你能够逐步深入到响应式数据处理和指令系统的奥秘之中。 项目技术分析 tiny-vue 主要分为两个关键部分:响应式S...

gitblog_00012的博客 637

第2期|【源码】vue3工具函数源码解读

学习笔记 源码解读第二期: 知其然,知其所以然 这个解读核心主要是shared模块, 对应的文件路径是:vue-next/packages/shared/src/index.ts 也可以用github1s访问,速度更快github1spackages/shared/src/index.ts 打包构建 按照贡献指南 的方法打包,把ts 转成js 打包前注意事项: Node.js 版本是 10+ yarn 的版本是 1.x Yarn 1.x。 node -v # v14.16.0 # 全局安装

rbgg_mp的博客 533
上一篇: 前端硬核知识点(三)
下一篇: 前端硬核知识点(四)
gcc_front
博客等级 码龄9年 16粉丝 98原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值