先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
正文
}
}
2、@hook
// 父组件
<Child @hook:mounted=“doSomething”/>
//子组件
组件通信方式
父子组件
1、props、$emit
2、 p a r e n t 、 parent、 parent、children
跨级组件
1、 a t t r s 、 attrs、 attrs、listeners
2、provide、inject
父子、跨级、兄弟
1、EventBus(事件总线)
2、Vuex(状态管理)
扩展
1、缓存
2、路由
具体细节参考文章
v-on监听多个方法
鼠标进来1
常用修饰符
表单修饰符
1、lazy::失去焦点后同步信息
2、trim:自动过滤首尾空格
3、number:输入值转为数值类型
事件修饰符
1、stop:阻止冒泡(js中stopPropagation)
2、prevent:阻止默认行为(js中preventDefault)
3、self:仅绑定元素自身触发
4、once:只触发一次
class、style的动态绑定方式
对象方式
数组方式
v-show与v-if的区别
相同点
都是控制页面元素的显示与隐藏
不同点
1、v-show 控制的是元素的CSS(v-show="false"相当于display:none);v-if 是控制元素本身的添加或删除(即是否出现在DOM结构中)
2、v-show 由 false 变为 true 的时候不会触发组件的生命周期。v-if 由 false 变为 true 则会触发组件的beforeCreate
、create
、beforeMount
、mounted
钩子,由 true 变为 false 会触发组件的beforeDestory
、destoryed
方法
3、频繁切换时,使用v-show;不频繁切换、加快页面渲染、需要销毁元素使用v-if
为什么v-if不能和v-for一起使用
性能浪费,每次渲染都要先循环再进行条件判断,考虑用计算属性替代。
Vue2.x中v-for
比v-if
更高的优先级。
Vue3.x中v-if
比 v-for
更高的优先级。
computed与watch的区别与使用场景
computed
计算属性,依赖其他属性值,且值具备缓存的特性。只有它依赖的属性值发生改变,下一次获取的值才会重新计算。
适用于数值计算,并且依赖于其他属性时。因为可以利用缓存特性,避免每次获取值,都需要重新计算。
watch
观察属性,监听属性值变动。每当属性值发生变化,都会执行相应的回调。
适用于数据变化时执行异步或开销比较大的操作。
具体细节参考文章
slot插槽的理解与使用
slot 插槽,可以理解为slot
在组件模板中提前占据了位置。当复用组件时,使用相关的slot标签时,标签里的内容就会自动替换组件模板中对应slot标签的位置,作为承载分发内容的出口。
具体细节参考文章
Vue.$delete和delete的区别
Vue.$delete 是直接删除了元素,改变了数组的长度;delete 是将被删除的元素变成内 undefined
,其他元素键值不变。
Vue.$set如何解决对象新增属性不能响应的问题
Vue.$set的出现是由于Object.defineProperty
的局限性:无法检测对象属性的新增或删除。
源码位置:vue/src/core/observer/index.js
export function set(target, key, val) {
// 数组
if(Array.isArray(target) && isValidArrayIndex(key)) {
// 修改数组长度,避免索引大于数组长度导致splice错误
target.length = Math.max(target.length, key)
// 利用数组splice触发响应
target.splice(key, 1, val)
return val
}
// key 已经存在,直接修改属性值
if(key in target && !(key in Object.prototype)) {
target[key] = val
return val
}
const ob = target.ob
// target 不是响应式数据,直接赋值
if(!ob) {
target[key] = val
return val
}
// 响应式处理属性
defineReactive(ob.value, key, val)
// 派发更新
ob.dep.notify()
return val
}
具体原理
1、若是数组,直接使用数组的 splice 方法触发响应式
2、若是对象,判断属性是否存在,对象是否是响应式
3、以上都不满足,最后通过 defineReactive 对属性进行响应式处理
具体细节参考文章
{{firstName}} {{lastName}} say {{alias}}
’,…![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://i-blog.csdnimg.cn/blog_migrate/90ed8453af0a0e81860f7d6fe927b451.png)
Vue.$nextTick的原理
nextTick:在下次 DOM 更新循环结束之后执行延迟回调。常用于修改数据后获取更新后的DOM。
源码位置:vue/src/core/util/next-tick.js
import { noop } from ‘shared/util’
import { handleError } from ‘./error’
import { isIE, isIOS, isNative } from ‘./env’
// 是否使用微任务标识
export let isUsingMicroTask = false
// 回调函数队列
const callbacks = []
// 异步锁
let pending = false
function flushCallbacks () {
// 表示下一个 flushCallbacks 可以进入浏览器的任务队列了
pending = false
// 防止 nextTick 中包含 nextTick时出现问题,在执行回调函数队列前,提前复制备份,清空回调函数队列
const copies = callbacks.slice(0)
// 清空 callbacks 数组
callbacks.length = 0
for (let i = 0; i < copies.length; i++) {
copiesi
}
}
let timerFunc
// 浏览器能力检测
// 使用宏任务或微任务的目的是宏任务和微任务必在同步代码结束之后执行,这时能保证是最终渲染好的DOM。
// 宏任务耗费时间是大于微任务,在浏览器支持的情况下,优先使用微任务。
// 宏任务中效率也有差距,最低的就是 setTimeout
if (typeof Promise !== ‘undefined’ && isNative(Promise)) {
const p = Promise.resolve()
timerFunc = () => {
p.then(flushCallbacks)
if (isIOS) setTimeout(noop)
}
isUsingMicroTask = true
} else if (!isIE && typeof MutationObserver !== ‘undefined’ && (
isNative(MutationObserver) ||
MutationObserver.toString() === ‘[object MutationObserverConstructor]’
)) {
let counter = 1
const observer = new MutationObserver(flushCallbacks)
const textNode = document.createTextNode(String(counter))
observer.observe(textNode, {
characterData: true
})
timerFunc = () => {
counter = (counter + 1) % 2
textNode.data = String(counter)
}
isUsingMicroTask = true
} else if (typeof setImmediate !== ‘undefined’ && isNative(setImmediate)) {
timerFunc = () => {
setImmediate(flushCallbacks)
}
} else {
timerFunc = () => {
setTimeout(flushCallbacks, 0)
}
}
export function nextTick (cb?: Function, ctx?: Object) {
let _resolve
// 将 nextTick 的回调函数用 try catch 包裹一层,用于异常捕获
// 将包裹后的函数放到 callback 中
callbacks.push(() => {
if (cb) {
try {
cb.call(ctx)
} catch (e) {
handleError(e, ctx, ‘nextTick’)
}
} else if (_resolve) {
_resolve(ctx)
}
})
// pengding 为 false, 执行 timerFunc
if (!pending) {
// 关上锁
pending = true
timerFunc()
}
if (!cb && typeof Promise !== ‘undefined’) {
return new Promise(resolve => {
_resolve = resolve
})
}
}
总结:
1、运用异步锁的概念,保证同一时刻任务队列中只有一个 flushCallbacks。当 pengding 为 false 的时候,表示浏览器任务队列中没有 flushCallbacks 函数;当 pengding 为 true 的时候,表示浏览器任务队列中已经放入 flushCallbacks;待执行 flushCallback 函数时,pengding 会被再次置为 false,表示下一个 flushCallbacks 可进入任务队列
2、环境能力检测,选择可选中效率最高的(宏任务/微任务)进行包装执行,保证是在同步代码都执行完成后再去执行修改 DOM 等操作
3、flushCallbacks 先拷贝再清空,为了防止nextTick嵌套nextTick导致循环不结束
具体细节参考如上文章
虚拟DOM的理解
虚拟 DOM 的出现解决了浏览器的性能问题。虚拟 DOM 是一个用 JS 模拟的 DOM 结构对象(Vnode),用于频繁更改 DOM 操作后不立即更新 DOM,而是对比新老 Vnode,更新获取最新的Vnode,最后再一次性映射成真实的 DOM。这样做的原因是操作内存中操作 JS 对象速度比操作 DOM 快很多。
举个例子
real dom
- item 1
- item 2
- item 3
用 JS 来模拟以上 DOM 节点实现虚拟 DOM
function Element(tagName, props, children) {
this.tageName = tagName
this.props = props || {}
this.children = children || []
this.key = props.key
let count = 0
this.children.forEach(child => {
if(child instanceof Element) count += child.count
count++
})
this.count = count
}
const tree = Element(‘div’, { id: container }, [
Element(‘p’, {}, [‘real dom’])
Element(‘ul’, {}, [
Element(‘li’, { class: ‘item’ }, [‘item1’]),
Element(‘li’, { class: ‘item’ }, [‘item2’]),
Element(‘li’, { class: ‘item’ }, [‘item3’])
])
])
虚拟 DOM 转为真实的节点
Element.prototype.render = function() {
let el = document.createElement(this.tagName)
let props = this.props
for(let key in props) {
el.setAttribute(key, props[key])
}
let children = this.children || []
children.forEach(child => {
let child = (child instanceof Element) ? child.render() : document.createTextNode(child)
el.appendChild(child)
})
return el
}
Diff算法原理
具体细节参考文章
key的作用
key 是 Vue 中 vnode 的唯一标记,我们的 diff 的算法中 sameVnode 和 updateChildren 中就使用到了 key。
sameVnode 用来判断是否为同一节点。常见的业务场景是一个列表,若 key 值是列表索引,在新增或删除的情况下会存在就地复用的问题。(简单说,复用了上一个在当前位置元素的状态)所以 key 值的唯一,确保 diff 更准确。
updateChildren 中当其中四种假设都未匹配,就需要依赖老节点的 key 和 索引创建关系映射表,再用新节点的 key 去关系映射表去寻找索引进行更新,这保证 diff 算法更加快速。
简单来说就是:根据key判断是否复用,实现高效渲染
动态组件 和 异步组件
动态组件通过
is
特性实现。适用于根据数据、动态渲染的场景,即组件类型不确定。具体细节参考官网
Vue.directive 有写过么,有哪些应用场景
Vue.directive 可以注册全局指令和局部指令。
指令定义函数提供如下钩子函数
1、bind:指令第一次绑定到元素时调用(只调用一次)
2、inserted: 被绑定元素插入父节点时使用(父节点存在即可调用)
3、update:被绑定元素所在模板更新时调用,不论绑定值是否变化。通过比较更新前后的绑定值
4、 componentUpdated: 被绑定元素所在模板完成一次更新周期时调用
5、unbind: 只调用一次,指令与元素解绑时调用
具体细节参考官网
Vue 过滤器
Vue 过滤器可用在两个地方:双花括号插值和 v-bind 表达式。
Vue3 中已经废弃这个特点。
过滤器分为 全局过滤器 和 局部过滤器。
局部过滤器
{{ name | formatName }}全局过滤器
Vue.filter(‘formatName’, function(value) {
// 可基于源值做一些处理
return value
})
过滤器可串联,执行顺序从左到右,第二个过滤器输入值是第一个过滤器的输出值
{{ name | formatName1 | formatName2 }}关于mixin的理解,有什么应用场景
mixin 混入分全局混入和局部混入,本质是 JS 对象,如 data、components、computed、methods 等。
全局混入不推荐使用,会影响后续每个Vue实例的创建。局部混入可提取组件间相同的代码,进行逻辑复用。
适用场景:如多个页面具备
相同
的悬浮定位浮窗,可尝试用 mixin 封装。具体细节参考文章
介绍一下keep-alive
具体细节参考文章
Vue-Router 配置 404 页面
* 代表通配符,若放在任意路由前,会被先匹配,导致跳转到 404 页面,所以需将如下配置置于最后。
{
path: ‘*’,
name: ‘404’
component: () => import(‘./404.vue’)
}
Vue-Router 有哪几种导航守卫
全局路由守卫
在路由跳转前触发,可在执行 next 方法前做一些身份登录验证的逻辑
const router = new VueRouter({
// 相关配置
})
// 全局路由守卫(跳转每个路由页面前统一处理)
router.beforeEach((to, from, next) => {
…
// 必须执行 next 方法来触发路由跳转
next()
})
全局后置钩子
和守卫不同的是,这些钩子不会接受
next
函数也不会改变导航本身// 全局后置钩子(跳转每个路由页面后统一处理)
router.afterEach((to, from) => {
// …
})
路由独享守卫
可在路由配置上直接定义 beforeEnter
const router = new VueRouter({
routes: [
{
path: ‘/home’,
component: Home,
// 只有该路由独享
beforeEnter: (to, from, next) => {
}
},
{
path: ‘/about’,
component: About
}
]
})
组件守卫
组件内可直接定义如下路由导航守卫
onst Foo = {
template:
...
,beforeRouteEnter(to, from, next) {
// 不能获取组件实例 this
// 当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
// 当前路由改变,但是组件被复用时调用
// 可访问实例 this
},
beforeRouteLeave(to, from, next) {
// 导航离开组件时被调用
}
}
更多细节参考官网
API 参考 | Vue Router
https://router.vuejs.org/zh/api/#router-link
Vue-Router 完整的导航解析流程
1、导航被触发
2、在失活的组件里调用 beforeRouteLeave 守卫
3、调用全局 beforeEach 前置守卫
4、重用的组件调用 beforeRouteUpdate 守卫(2.2+)
5、路由配置调用 beforeEnter
6、解析异步路由组件
7、在被激活的组件里调用 beforeRouteEnter 守卫
8、调用全局的 beforeResolve 守卫(2.5+)
9、导航被确认
10、调用全局的 afterEach
11、触发 DOM 更新
12、调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入
推荐本人对Vue router的详细介绍博客
Vuex 的理解及使用
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,采用集中式存储管理应用的所有组件的状态。
主要解决如下 两个 问题
1、多个视图依赖同一状态。
2、来自不同视图的行为需要变更同一个状态。
其包含如下模块
State:定义并初始化全局状态。
Getter:依赖 State 中的状态,进行二次包装,不会影响 State 源数据。
Mutation:更改 State 状态的函数,必须是同步。
Action:用于提交 Mutation,可包含任意异步操作。
Module:若应用复杂,Store 会集中一个比较大的对象而显得臃肿,Module允许我们将 Store模块化管理。
当然,若应用比较简单,共享状态也比较少,可以用 Vue.observe 去替代 Vuex,省去安装一个库也挺好。
具体细节参考文章
Vuex 刷新后数据丢失怎么办
持久化缓存:localStorage、sessionStorage
Vuex 如何知道 State 是通过 Mutation 修改还是外部修改
Vuex 中修改 state 唯一渠道是执行 commit 方法,底层通过执行 this._withCommit(fn),且设置_committing标识符为 true,才能修改 state,修改完还需要将标识符置为 false。外部修改是无法设置标识位的,所以通过 watch 监听 state 变化,来判断修改的合法性。
Vue SSR 了解么
Vue SSR 项目中暂时还没有运用过,后续会写个 Demo 单独成文吧。这边搬运下其他答案。
SSR 服务端渲染,将 HTML 渲染工作放在服务端完成后,将 HTML 返回到浏览器端。
优点:SSR有更好的 SEO,首屏加载更快。
缺点:服务端负载大。
如果是内部系统,SSR其实没有太多必要。如果是对外的项目,维护高可用的node服务器是个难点。
Vue2 与 Vue3 的区别 ?Vue3有哪些优化点?
具体细节参考本人博客对Vue3的详细介绍
Vue 性能优化
1、非响应式数据通过 Object.freeze 冻结数据
2、嵌套层级不要过深
3、computed 和 watch 区别使用
4、v-if 和 v-show 区别使用
文末
我一直觉得技术面试不是考试,考前背背题,发给你一张考卷,答完交卷等通知。
首先,技术面试是一个 认识自己 的过程,知道自己和外面世界的差距。
更重要的是,技术面试是一个双向了解的过程,要让对方发现你的闪光点,同时也要 试图去找到对方的闪光点,因为他以后可能就是你的同事或者领导,所以,面试官问你有什么问题的时候,不要说没有了,要去试图了解他的工作内容、了解这个团队的氛围。
前端面试题汇总
JavaScript
性能
linux
前端资料汇总
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
tch 监听 state 变化,来判断修改的合法性。Vue SSR 了解么
Vue SSR 项目中暂时还没有运用过,后续会写个 Demo 单独成文吧。这边搬运下其他答案。
SSR 服务端渲染,将 HTML 渲染工作放在服务端完成后,将 HTML 返回到浏览器端。
优点:SSR有更好的 SEO,首屏加载更快。
缺点:服务端负载大。
如果是内部系统,SSR其实没有太多必要。如果是对外的项目,维护高可用的node服务器是个难点。
Vue2 与 Vue3 的区别 ?Vue3有哪些优化点?
具体细节参考本人博客对Vue3的详细介绍
Vue 性能优化
1、非响应式数据通过 Object.freeze 冻结数据
2、嵌套层级不要过深
3、computed 和 watch 区别使用
4、v-if 和 v-show 区别使用
文末
我一直觉得技术面试不是考试,考前背背题,发给你一张考卷,答完交卷等通知。
首先,技术面试是一个 认识自己 的过程,知道自己和外面世界的差距。
更重要的是,技术面试是一个双向了解的过程,要让对方发现你的闪光点,同时也要 试图去找到对方的闪光点,因为他以后可能就是你的同事或者领导,所以,面试官问你有什么问题的时候,不要说没有了,要去试图了解他的工作内容、了解这个团队的氛围。
前端面试题汇总
JavaScript
性能
linux
前端资料汇总
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-ZIUE5Qbi-1713043693009)]一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!