Vue-Lifecycle

本文深入探讨了Vue实例的初始化过程,包括Vue.prototype._init函数的执行,options的合并策略,以及生命周期钩子的处理。通过mergeOptions函数,详细阐述了如何递归合并父组件与子组件的选项,并根据LIFECYCLE_HOOKS定义的生命周期钩子进行合并。此外,还介绍了callHook函数在触发生命周期钩子时的作用。整个过程揭示了Vue实例从创建到销毁的完整生命周期。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生命周期

new Vue

export function initMixin(Vue) {
	Vue.prototype._init = function(options) {
		const vm = this;
		vm.$options = mergeOptions(
			resolveConstructorOptions(vm.constructor),
			options || {},
			vm
		)
		vm._selft = vm;
		initLifecycle(vm); // 初始化声明周期
		initEvents(vm);	// 初始化事件
		initRender(vm); // 初始化渲染
		callHook(vm, 'beforeCreate'); // 调用beforeCreate hook
		initInjections(vm); // 调用injections
		initState(vm); // 初始化porps, methods, data, computed, watch
		initProvide(vm); // 初始化provide
		callHook(vm, 'created');
		
		if(vm.$options.el) {
            vm.$mount(vm.$options.el);
		}
	}
}

合并属性

合并options

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

resolveConstructorOptions(vm.constructor)的返回值和传入的options合并,这里的resolveConstructorOptions其实就是解析出构造函数的options选项,这里传入vm.constructor所以得出的是Vue.options,下面是Vue.options的定义

src/core/global-api/index.js

export function initGloabAPI(Vue: GlobalAPI) {
    Vue.options = Object.create(null);
    ASSET_TYPES.forEach(type => {
        Vue.options[`${type}s`] = Object.create(null)
    })
    
    extend(Vue.options.components, builtInComponents);
}

export const ASSET_TYPES = [
    'componet',
    'directive',
    'filter'
]

extend 语句执行之后,所有的内置组件都被注册,所以我们不需要自己去注册这些组件

mergeOptions

src/core/util/options.js

export function mergeOptions (
	parent: Object,
    child: Object,
    vm?: Component
): Object {
    if(typeof child === 'function') {
        child = child.options;
	}
    
    const extendsFrom = child.extends
    if(extendsFrom) {
        // 递归合并extends
        parent = mergeOptions(parent, extendsFrom, vm);
	}
    
    if(child.mixins) {
        for(let i = 0, l = child.mixins.length; i < 1; i++) {
            // 递归合并mixins
            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)) { // child特有的属性(parent中没有的)
            mergeField(key);
        }
    }
    
	function mergeField(key) {
        // strat是strategy的缩写(策略模式),对于不同类型的数据有着不同的合并策略。
        // 不同的合并策略由传入的key决定
        // data watch props compputed......
        const strat = strats[key] || defaultStrat;
        options[key] = strat(parent[key], child[key], vm, key);
	}
    return options;
}

mergeField

Eg:合并hooks

function mergeHook(parentVal, childVal) : {
    return childVal
    	? parentVal
    		? parentVal.concat(childVal)
    		: Array.isArray(child)
                ? child
                : [child]
    	:parentVal
}

LIFECYCLE_HOOKS.forEach(hook => {
    strats[hook] = mergeHook;
})

src/shared/constants.js

export const LIFECYCLE_HOOKS = [
  'beforeCreate',
  'created',
  'beforeMount',
  'mounted',
  'beforeUpdate',
  'updated',
  'beforeDestroy',
  'destroyed',
  'activated',
  'deactivated',
  'errorCaptured'
]

由于Vue支持mixins模式,到达触发某个钩子函数的时候其实是需要触发多个函数的,所以需要用一个数组来保存。(发布-订阅模式)

上面的三元表达式的意思是:如果childVal存在,parentVal存在那么两者合并返回,如果childVal存在parentVal不存在,那么判断childVal是否是数组,如果是那么直接返回,如果不是那么加上数组包裹。如果childVal不存再那么直接返回parentVal

callHook函数触发

src/core/instance/lifecycle.js

// 发布过程
export function callHook(vm: Componet, hook: string) {
    const handlers = vm.$options[hook];
    if(handlers) {
        for(let i = 0;m j = handlers.length; i < j; i++) {
            try{
                handlers[i].call(vm);
			} catch(e) {
                handleError(e, vm, `${hook} hook`);
            }
		}
	}
}

initLifecycle

0 info it worked if it ends with ok 1 verbose cli [ 1 verbose cli 'E:\\web_study\\node\\nodejs\\node.exe', 1 verbose cli 'E:\\web_study\\node\\nodejs\\node_modules\\npm\\bin\\npm-cli.js', 1 verbose cli 'run', 1 verbose cli 'build' 1 verbose cli ] 2 info using npm@6.14.5 3 info using node@v14.5.0 4 verbose run-script [ 'prebuild', 'build', 'postbuild' ] 5 info lifecycle vue-antd-jeecg@3.4.3~prebuild: vue-antd-jeecg@3.4.3 6 info lifecycle vue-antd-jeecg@3.4.3~build: vue-antd-jeecg@3.4.3 7 verbose lifecycle vue-antd-jeecg@3.4.3~build: unsafe-perm in lifecycle true 8 verbose lifecycle vue-antd-jeecg@3.4.3~build: PATH: E:\web_study\node\nodejs\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin;E:\java-study-item\jeecgboot-vue2\ant-design-vue-jeecg\node_modules\.bin;E:\Software\MySQL\mysql-8.0.26-winx64\bin;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;E:\web_study\node\nodejs;E:\Git\Git-install\Git\cmd;E:\linux\tools\xshell\;E:\linux\tools\xftp\;E:\Developer\Developer_tools\java\jdk1.8.0_211\bin;C:\Users\SHUAIGE\AppData\Local\Microsoft\WindowsApps;E:\web_study\html\cvcode\Microsoft VS Code\bin;E:\maven\apache-maven-3.8.4\bin;E:\Software\idea\Installation package\IntelliJ IDEA 2020.3.1\bin;;C:\Users\SHUAIGE\AppData\Roaming\npm;E:\web_study\node\nodejs;D:\软件下载\bandizip\ 9 verbose lifecycle vue-antd-jeecg@3.4.3~build: CWD: E:\java-study-item\jeecgboot-vue2\ant-design-vue-jeecg 10 silly lifecycle vue-antd-jeecg@3.4.3~build: Args: [ '/d /s /c', 'vue-cli-service build' ] 11 silly lifecycle vue-antd-jeecg@3.4.3~build: Returned: code: 1 signal: null 12 info lifecycle vue-antd-jeecg@3.4.3~build: Failed to exec build script 13 verbose stack Error: vue-antd-jeecg@3.4.3 build: `vue-cli-service build` 13
最新发布
03-31
<think>好的,我现在需要解决用户在vue-antd-jeecg项目中执行npm run build失败的问题,错误代码是1,提示vue-cli-service build的问题。根据用户提供的引用内容,我需要逐步分析可能的原因和解决方法。 首先,用户提到npm run build报错,错误信息是找不到vue-cli-service。根据引用[1]、[3]、[5],这通常是因为依赖未正确安装。可能的解决步骤包括删除node_modules和package-lock.json,然后重新安装依赖。此外,引用[4]提到使用yarn安装可能更可靠,而引用[2]则讨论了production设置的影响,可能需要调整npm的配置。 接下来,我需要整理这些信息,分步骤说明解决方法。首先检查是否存在node_modules目录,如果没有,需要执行npm install。如果已经存在,可能需要清除缓存并重新安装。另外,使用yarn代替npm可能有效,特别是项目可能推荐使用yarn。同时,检查npm的production设置是否正确,确保在开发环境下不要启用production模式,因为这会跳过开发依赖的安装,而vue-cli-service属于开发依赖。 可能还需要确认package.json中的scripts部分是否正确,是否有build脚本指向vue-cli-service build。此外,检查项目结构,确认vue-cli-service的路径是否存在,有时候路径错误或文件缺失会导致问题。 用户可能已经尝试过npm install,但可能由于缓存问题或安装中断导致依赖不完整。因此,清理缓存、删除lock文件和node_modules后重新安装是关键步骤。如果使用npm无效,换用yarn可能解决依赖解析的问题。 最后,如果问题依旧存在,可能需要检查项目本身的配置或查看是否有已知的问题在jeecg的issue中,或者环境问题如Node.js和npm版本是否符合要求。</think>针对`vue-antd-jeecg`项目执行`npm run build`失败的问题(错误代码1,提示`vue-cli-service build`),以下是逐步排查与解决方法: --- ### **步骤1:清理缓存与重新安装依赖** 1. **删除现有依赖与锁定文件** 在项目根目录下执行以下命令,清除可能损坏的依赖: ```bash rm -rf node_modules/ package-lock.json yarn.lock ``` 2. **清理npm缓存** ```bash npm cache clean --force ``` 3. **重新安装依赖** - 如果项目推荐使用`yarn`(如引用[4]): ```bash npm install -g yarn # 全局安装yarn(如未安装) yarn install # 使用yarn安装依赖 ``` - 如果使用`npm`: ```bash npm install ``` --- ### **步骤2:检查npm生产模式配置** 根据引用[2],`npm`的`production`模式可能导致开发依赖缺失(`vue-cli-service`属于开发依赖): 1. **查看当前配置** ```bash npm config get production ``` - 如果返回`true`,需关闭生产模式: ```bash npm config set production false ``` 2. **重新安装依赖** ```bash npm install ``` --- ### **步骤3:验证vue-cli-service路径** 确保`vue-cli-service`存在于`node_modules/.bin`目录中: 1. 检查文件是否存在: ```bash ls node_modules/.bin/vue-cli-service ``` - 如果不存在,说明依赖安装不完整,需重复**步骤1**。 --- ### **步骤4:检查Node.js与npm版本** 1. **Node.js版本** 确保使用`Node.js 14.x`或更高版本(Vue CLI要求)。 ```bash node -v ``` 2. **npm版本** 升级到最新稳定版: ```bash npm install -g npm@latest ``` --- ### **步骤5:检查项目配置** 1. **查看`package.json`脚本** 确认`build`脚本是否正确: ```json "scripts": { "build": "vue-cli-service build" } ``` 2. **检查项目结构** 确保项目根目录包含`vue.config.js`(如有自定义配置)且无语法错误。 --- ### **步骤6:参考项目特定解决方案** 如果问题仍存在,参考`jeecg`官方文档或GitHub仓库的Issue,可能存在已知的构建配置问题。例如: - 调整`babel`或`webpack`配置 - 排除特定依赖冲突(如引用[2]中提到的生产环境设定) --- ### **最终修复命令示例** ```bash # 清理环境 rm -rf node_modules package-lock.json npm cache clean --force # 使用yarn安装(推荐) npm install -g yarn yarn install # 重新构建 npm run build ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值