2024年Web前端最新深入浅出 Vue Mixin,高级前端面试题及答案

下面是我在学习HTML和CSS的时候整理的一些笔记,有兴趣的可以看下:

HTML、CSS部分截图

进阶阶段

进阶阶段,开始攻 JS,对于刚接触 JS 的初学者,确实比学习 HTML 和 CSS 有难度,但是只要肯下功夫,这部分对于你来说,也不是什么大问题。

JS 内容涉及到的知识点较多,看到网上有很多人建议你从头到尾抱着那本《JavaScript高级程序设计》学,我是不建议的,毕竟刚接触 JS 谁能看得下去,当时我也不能,也没那样做。

我这部分的学习技巧是,增加次数,减少单次看的内容。就是说,第一遍学习 JS 走马观花的看,看个大概,去找视频以及网站学习,不建议直接看书。因为看书看不下去的时候很打击你学下去的信心。

然后通过一些网站的小例子,开始动手敲代码,一定要去实践、实践、实践,这一遍是为了更好的去熟悉 JS 的语法。别只顾着来回的看知识点,眼高手低可不是个好习惯,我在这吃过亏,你懂的。

1、JavaScript 和 ES6

在这个过程你会发现,有很多 JS 知识点你并不能更好的理解为什么这么设计,以及这样设计的好处是什么,这就逼着让你去学习这单个知识点的来龙去脉,去哪学?第一,书籍,我知道你不喜欢看,我最近通过刷大厂面试题整理了一份前端核心知识笔记,比较书籍更精简,一句废话都没有,这份笔记也让我通过跳槽从8k涨成20k。

JavaScript部分截图

2、前端框架

前端框架太多了,真的学不动了,别慌,其实对于前端的三大马车,Angular、React、Vue 只要把其中一种框架学明白,底层原理实现,其他两个学起来不会很吃力,这也取决于你以后就职的公司要求你会哪一个框架了,当然,会的越多越好,但是往往每个人的时间是有限的,对于自学的学生,或者即将面试找工作的人,当然要选择一门框架深挖原理。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

以 Vue 为例,我整理了如下的面试题。

Vue部分截图

if (version >= 2) {

Vue.mixin({ beforeCreate: vuexInit })

} else {

// override init and inject vuex init procedure

// for 1.x backwards compatibility.

const _init = Vue.prototype._init

Vue.prototype._init = function (options = {}) {

options.init = options.init

? [vuexInit].concat(options.init)

: vuexInit

_init.call(this, options)

}

}

/**

* Vuex init hook, injected into each instances init hooks list.

*/

function vuexInit () {

const options = this.$options

// store injection

if (options.store) {

this.$store = typeof options.store === ‘function’

? options.store()

: options.store

} else if (options.parent && options.parent.$store) {

this. s t o r e   =   o p t i o n s . p a r e n t . store = options.parent. store = options.parent.store

}

}

}

我们看到 在 Vue 2.0 以上版本,通过 Vue.mixin({ beforeCreate: vuexInit })实现了在每一个实例的 beforeCreate 生命周期调用vuexInit 方法。

而 vuexInit 方法则是:在跟节点我们会直接把store 注入,在其他节点则拿父级节点的 store,这样this.$store 永远是你在根节点注入的那个store。

vue mixin 源码实现


在 Vuex 的例子中,我们通过 Vue.mixin({ beforeCreate: vuexInit }) 实现对实例的 $store 扩展。

全局 mixin 注册

我们先看一下 mixin 是如何挂载到原型上的。

在 src/core/index.js 中:

import Vue from ‘./instance/index’

import { initGlobalAPI } from ‘./global-api/index’

initGlobalAPI(Vue)

export default Vue

我们发现有一个 initGlobalAPI。在 src/global-api/index 中:

/* @flow */

import config from ‘…/config’

import { initUse } from ‘./use’

import { initMixin } from ‘./mixin’

import { initExtend } from ‘./extend’

import { initAssetRegisters } from ‘./assets’

import { set, del } from ‘…/observer/index’

import { ASSET_TYPES } from ‘shared/constants’

import builtInComponents from ‘…/components/index’

import {

warn,

extend,

nextTick,

mergeOptions,

defineReactive

} from ‘…/util/index’

export function initGlobalAPI (Vue: GlobalAPI) {

// config

const configDef = {}

configDef.get = () => config

if (process.env.NODE_ENV !== ‘production’) {

configDef.set = () => {

warn(

‘Do not replace the Vue.config object, set individual fields instead.’

)

}

}

Object.defineProperty(Vue, ‘config’, configDef)

// exposed util methods.

// NOTE: these are not considered part of the public API - avoid relying on

// them unless you are aware of the risk.

Vue.util = {

warn,

extend,

mergeOptions,

defineReactive

}

Vue.set = set

Vue.delete = del

Vue.nextTick = nextTick

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)

}

所有全局的方法都在这里注册。我们关注 initMixin 方法,定义在 src/core/global-api/mixin.js:

import { mergeOptions } from ‘…/util/index’

export function initMixin (Vue: GlobalAPI) {

Vue.mixin = function (mixin: Object) {

this.options = mergeOptions(this.options, mixin)

return this

}

}

至此我们发现了 Vue 如何挂载全局 mixin。

mixin 合并策略

vuex 通过 beforeCreate Hook 实现为所有 vm 添加 $store 实例。让我们先把 hook 的事情放一边。看一看 beforeCreate 如何实现。

在 src/core/instance/init.js 中:

export function initMixin (Vue: Class) {

Vue.prototype._init = function (options?: Object) {

// remove unrelated code

initLifecycle(vm)

initEvents(vm)

initRender(vm)

callHook(vm, ‘beforeCreate’)

initInjections(vm) // resolve injections before data/props

initState(vm)

initProvide(vm) // resolve provide after data/props

callHook(vm, ‘created’)

// remove unrelated code

if (vm.$options.el) {

vm. m o u n t ( v m . mount(vm. mount(vm.options.el)

}

}

}

我们可以看到在 initRender 完成后,会调用 callHook(vm, 'beforeCreate')。而 init 实在 vue 实例化会执行的。

在 src/core/instance/lifecycle.js 中:

export function callHook (vm: Component, hook: string) {

// #7573 disable dep collection when invoking lifecycle hooks

pushTarget()

const handlers = vm.$options[hook]

if (handlers) {

for (let i = 0, j = handlers.length; i < j; i++) {

try {

handlers[i].call(vm)

} catch (e) {

handleError(e, vm, ${hook} hook)

}

}

}

if (vm._hasHookEvent) {

vm.$emit(‘hook:’ + hook)

}

popTarget()

}

在对 beforeCreate 执行 callHook 过程中,会先从 vue 实例的 options 中取出所有挂载的 handlers。然后循环调用 call 方法执行所有的 hook:

handlers[i].call(vm)

由此我们可以了解到全局的 hook mixin 会和要 mixin 的组件合并 hook,最后生成一个数组。

回头再看:

import { mergeOptions } from ‘…/util/index’

export function initMixin (Vue: GlobalAPI) {

Vue.mixin = function (mixin: Object) {

this.options = mergeOptions(this.options, mixin)

return this

}

}

this.options 默认是 vue 内置的一些 option:

image

mixin 就是你要混入的对象。我们来看一看 mergeOptions。定义在 src/core/util/options.js:

export function mergeOptions (

parent: Object,

child: Object,

vm?: Component

): Object {

if (process.env.NODE_ENV !== ‘production’) {

checkComponents(child)

}

if (typeof child === ‘function’) {

child = child.options

}

normalizeProps(child, vm)

normalizeInject(child, vm)

normalizeDirectives(child)

const extendsFrom = child.extends

if (extendsFrom) {

parent = mergeOptions(parent, extendsFrom, 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

}

忽略不相干代码我们直接跳到:

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)

}

此时 child 为 { beforeCreate: vuexInit }。走入到 mergeField 流程。mergeField 先取合并策略。

const strat = strats[key] || defaultStrat,相当于取 strats[‘beforeCreate’] 的合并策略。定义在通文件的上方:

/**

* Hooks and props are merged as arrays.

*/

function mergeHook (

parentVal: ?Array,

childVal: ?Function | ?Array

): ?Array {

return childVal

? parentVal

? parentVal.concat(childVal)

: Array.isArray(childVal)

? childVal

: [childVal]

: 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’

]

在  mergeHook 中的合并策略是把所有的 hook 生成一个函数数组。其他相关策略可以在options 文件中查找(如果是对象,组件本身的会覆盖上层,data 会执行结果,返回再merge,hook则生成数组)。

mixin 早于实例化

mergeOptions 会多次调用,正如其注释说描述的那样:

/**

* Merge two option objects into a new one.

* Core utility used in both instantiation and inheritance.

*/

上面介绍了全局 mixin 的流程,我们来看下 实例化部分的流程。在 src/core/instance/init.js 中:

最后

除了简历做到位,面试题也必不可少,整理了些题目,前面有117道汇总的面试到的题目,后面包括了HTML、CSS、JS、ES6、vue、微信小程序、项目类问题、笔试编程类题等专题。

  • 12
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值