赞
踩
Vue2只能一个根节点
Vue3在组件中可以放置多个根节点
vue2:采用的选项型API(opsition API)
vue3:采用的组合型API(composition API)
vue2:数据是放置在data属性中
vue3:需要使用setup 方法,该方法在初始化构造的时候触发
注:ref:需要value 访问,内部还是使用的defineProperty set get 方法进行监听(proxy 不支持基本类型的监听)
reactive: 使用的proxy对数据进行的一个代理
vue2:父传子,用props,子传父用事件 Emitting Events。在vue2中,会调用this$emit然后传入事件名和对象。
vue3:父传子,用props,子传父用事件 Emitting Events。在vue3中的setup()中的第二个参数content对象中就有emit,那么我们只要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。
M - Model 数据:负责数据管理和业务逻辑。
V - View 视图:负责用户界面的展示和呈现。
VM - ViewModel 视图-数据:它是View和Model的粘合体,负责View和Model的交互和协作
vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;
核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法,get set 方法。
在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信。
MVVM 是一种软件架构模式。它是基于 MVC 的一种演变,将视图和数据绑定的方式更加紧密地结合在一起。
M - Model 数据:负责数据管理和业务逻辑。模型表示应用程序中的数据结构以及对数据的操作。
V - View 视图:负责用户界面的展示和呈现,通常是用户可以看到和与之交互的部分。
C - Controller 控制器: 负责接收用户的输入并作出响应,它处理用户与模型和视图之间的交互。控制器将用户的操作转发给模型进行处理,并将模型的结果传递给视图进行展示。
MVC 的优势:
能够将应用程序的各个功能模块分离开来,提高代码的可维护性和可扩展性。通过明确定义了各个组件的职责,开发人员可以更好地组织和管理代码,同时也使得代码更容易被复用。
1、mvvm各部分的通信是双向的,而mvc各部分通信是单向的;
2、mvvm是真正将页面与数据逻辑分离放到js里去实现,而mvc里面未分离。
MVC允许在不改变视图的情况下改变视图对用户输入的响应方式,用户对View的操作交给了Controller处理,在Controller中响应View的事件调用Model的接口对数据进行操作,一旦Model发生变化便通知相关视图进行更新。
对象类型:
使用 Object.defineProperty 遍历对象的每一个属性,把每一个属性变成一个 getter 和 setter 函数,读取属性的时候调用 getter,给属性赋值的时候就会调用 setter,这就是数据劫持。
数组类型:
通过重写更新数组的一系列方法,保留原功能的基础上增加一些数据劫持的代码(也就是将数据变为可监控的)来实现拦截。
7个方法:push、pop、shift、unshift、splice、sort、reverse。
存在问题:
1.新增属性、删除属性, 界面不会更新。
2.直接通过下标修改数组, 界面不会自动更新。
解决方法:
vue2中 $set 可以解决这些问题。
通过(Proxy)代理实现: 拦截对象中任意属性的变化, 包括属性值的读写, 属性的添加, 属性的删除等操作。
通过(Reflect)(反射); 被代理的对象, 属性进行操作。
vue3.0 中不存在vue2.0 中说的这些问题
在一个对象中新增, 删除, 修改属性, 界面不会自动更新。
直接通过下标修改数组, 界面不会自动更新。
1)Proxy的优势如下:
- Proxy可以直接监听对象⽽⾮属性 。
- Proxy可以直接监听数组的变化 。
- Proxy有多达13种拦截⽅法,不限于apply、ownKeys、deleteProperty、has等等是 Object.defineProperty 不具备的 。
- Proxy返回的是⼀个新对象,我们可以只操作新的对象达到⽬的,⽽ Object.defineProperty 只能遍历对象属性直接修改。
- Proxy作为新标准将受到浏览器⼚商重点持续的性能优化,也就是传说中的新标准的性能红利 。
2)Object.defineProperty的优势如下:
- 兼容性好,⽀持IE9。
diff 算法有以下过程:
- 同级比较,再比较子节点
- 先判断一方有子节点一方没有子节点的情况(如果新的 children 没有子节点,将旧的子节点移除)
- 比较都有子节点的情况(核心 diff)
- 递归比较子节点
Vue2:
Vue2 的核心 Diff 算法采用了双端比较的算法,同时从新旧 children 的两端开始进行比较,借助 key 值找到可复用的节点,再进行相关操作。相比 React 的 Diff 算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。
Vue3:
Vue3.x 借鉴了 ivi 算法和 inferno 算法
在创建 VNode 时就确定其类型,以及在 mount/patch 的过程中采用位运算来判断一个 VNode 的类型,在这个基础之上再配合核心的 Diff 算法,使得性能上较 Vue2.x 有了提升。该算法中还运用了动态规划的思想求解最长递归子序列。
详细内容比较多,但这个是重点部分。请跳转至:
优点:
- 性能优化:虚拟DOM通过减少不必要的DOM操作,提高渲染性能。它使用一个高效的diff算法来计算出真正需要更新的节点,最大限度地减少DOM操作,从而提高性能。
- 抽象化DOM操作:由于虚拟DOM以JavaScript对象为基础,不依赖真实平台环境,因此可以跨平台操作,例如在浏览器平台、Weex、Node等环境中使用。
- 无需手动操作DOM:Vue的虚拟DOM可以自动处理视图更新,开发者只需要关注数据变化,无需手动操作DOM,大大提高了开发效率。
缺点:
- 首次渲染大量DOM时性能较差:由于虚拟DOM需要进行计算和比较,所以在首次渲染大量DOM时,可能会比直接操作DOM慢。
- 不适合小型项目:对于小型项目或简单页面,使用虚拟DOM可能会增加额外的计算开销,此时直接操作DOM可能更为简单高效。
Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载 Dom -> 渲染、更新 -> 渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
创建阶段:
beforeCreate:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created:在实例创建完成后被调用,此阶段完成了数据观测 (data observer)、属性和方法的运算,以及 watch/event 事件的设置。但是此时还没有挂载到 DOM 上。挂载阶段:
beforeMount:在挂载开始之前被调用,相关的 render 函数首次被调用。
mounted:在实例被挂载到 DOM 后调用,此阶段完成了模板编译并且将实例挂载到 DOM 上。
更新阶段:
beforeUpdate:在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁之前。
updated:在数据更新完成后被调用,实例的 DOM 已经更新。
销毁阶段:
beforeDestroy:在实例销毁之前调用,此时实例仍然完全可用。
destroyed:在实例销毁后调用,此阶段完成了实例的事件监听器和子组件的销毁。
两个特殊的生命周期钩子函数:
activated:在使用 keep-alive 组件时,被激活的组件会调用该函数。
deactivated:在使用 keep-alive 组件时,被停用的组件会调用该函数。
1)普通写法: | 2)setup中写生命周期: |
beforeCreate | setup() |
created | setup() |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
执行顺序:
父组件先创建,然后子组件创建;子组件先挂载,然后父组件挂载。
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
销毁过程:
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。
但是本人推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:
- 能更快获取到服务端数据,减少页面 loading 时间;
- ssr 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;
比如有父组件 Parent 和子组件 Child,如果父组件监听到子组件挂载 mounted 就做一些逻辑处理,可以通过以下写法实现:
// Parent.vue <Child @mounted="doSomething"/> // Child.vue mounted() { this.$emit("mounted"); }以上需要手动通过 $emit 触发父组件的事件,更简单的方式可以在父组件引用子组件时通过 @hook 来监听即可,如下所示
// Parent.vue <Child @hook:mounted="doSomething" ></Child> doSomething() { console.log('父组件监听到 mounted 钩子函数 ...'); }, // Child.vue mounted(){ console.log('子组件触发 mounted 钩子函数 ...'); }, // 以上输出顺序为: // 子组件触发 mounted 钩子函数 ... // 父组件监听到 mounted 钩子函数 ...当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件,例如:created,updated 等都可以监听。
在组件切换过程中将状态保留在内存中,防止重复渲染DOM,提高页面加载性能与用户体验
可以设置以下
props
属性(参数):
- include:匹配的路由/组件会被缓存
- exclude:匹配的路由/组件不会被缓存
- max:最大缓存数
当时用
keep-alive
,只会创建一次,即时切出该组件,也不会销毁该组件,再进入该组件,也不会创建。当引入
keep-alive
的时候,页面第一次进入,钩子的触发顺序 created => mounted => activated。退出时触发deactivated。当再次进入或退出时,只触发activated和deactivated。钩子的触发顺序(destroyed => activated )
因为 Vue 在创建组件实例时,会为每个组件实例都创建一个独立的数据作用域。
如果将 data 直接定义为一个对象,那么所有组件实例都将共享同一个数据对象,这样就无法实现数据的隔离。
data 是函数的话那么每次创建组件实例时,都会调用这个函数并返回一个新的对象。
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较。
作用:
是为了更高效的更新虚拟DOM,它的作用是标识虚拟DOM的唯一性,当虚拟DOM发生变化时,vue会根据key的变化来判断是否需要更新虚拟DOM。通过key的作用,可以更高效地更新虚拟DOM,提高了页面的性能和用户体验。
computed:计算属性,依赖于其他属性,并且computed的值有缓存。只有它依赖的属性值(响应式依赖)发生变化,下一次获取computed的值时才会重新计算computed的值。
watch:更多的是【观察】的作用,类似于某些数据的监听回调,每当监听的数据发生变化时,都会执行回调进行后续操作。
运用场景:
- computed:当我们要进行数值计算,并且依赖于其他数据时,这时应该使用computed,因为利用computed的缓存特性,可以避免每次获取值时都重复计算。
- watch: 当我们在数据发生变化时执行异步或开销较大的操作时,应该使用watch,使用watch选项允许我们执行一步操作(访问一个API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些是computed(计算属性)无法实现的
watch 和 watchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式
- watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。
- watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确
执行时机不同:
watch 是惰性地执行副作用,他不会立即执行,但可以配置immediate,使其主动触发 。
watchEffect 是立即执行的,在页面加载时会主动执行一次,来收集依赖。
参数不同:
watch 至少要有两个参数,第一个是监听的数据,第二个是回调函数,第三个是配置项。
watchEffect 只需要一个回调函数,不需要传递侦听的数据,它会在页面加载时主动执行一次,来收集依赖。
结果不同:
watch 可以获取新值和旧值。
watchEffect 获取不到更改前的值。
watchEffect的解释:
1、立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数
2、如果你需要侦听一个嵌套数据结构中的几个属性,watchEffect() 可能会比深度侦听器更有效,因为它将只跟踪回调中被使用到的属性,而不是递归地跟踪所有的属性。
1)props / $emit
父组件通过 props 向子组件传递数据,子组件通过 $emit 和父组件通信
2)ref / $refs
给子组件绑定ref,父组件通过 $refs. 读取子组件的属性和方法
3)eventBus事件总线($emit / $on)
4)依赖注入(provide / inject)
子组件 inject , 父组件 provide
pc:依赖注入所提供的属性是非响应式的。
5) $parent / $children
$parent 访问到的是上一级父组件的实例
$children 的值是数组,而 $parent是个对象
6)$attrs / $listeners
7)Vuex 和 Pinia
总结:
父子组件间通信
1)props,emit
2) ref,$refs
3)provide,inject
跨代组件间通信
1)$attrs,$listeners
兄弟组件间通信
1) $parent + $refs
任意组件间通信
1)eventBus事件总线
2)Vuex 和 Pinia
详解:
vue2 中 v-for 的优先级更高。(2o)
vue3 中优先级改变了,v-if 的优先级更高。 (3i)
同一个标签中同时使用了 v-for 和 v-if:
由于v-for的优先级比v-if高,所以每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。
解决办法:
1)用计算属性去过滤v-for使用的数组
2)添加 <template> 让 v-for 和 v-if,不在同一标签上
v-if :
是真正的条件渲染,动态的向DOM树内添加或者删除DOM元素
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
v-show :
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 “display” 属性进行切换。
总结:
所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。
delete:
只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。
Vue.delete :
是直接将元素从数组中完全删除,改变了数组其他元素的键值。
局部注册:
<script setup> // 在模板中启用 v-focus const vFocus = { mounted: (el) => el.focus() } </script> <template> <input v-focus /> </template>全局注册:
const app = createApp({}) // 使 v-focus 在所有组件中都可用 app.directive('focus', { /* ... */ })指令钩子:
const focus= { // 在绑定元素的 attribute 前 // 或事件监听器应用前调用 created(el, binding, vnode, prevVnode) { // 下面会介绍各个参数的细节 }, // 在元素被插入到 DOM 前调用 beforeMount(el, binding, vnode, prevVnode) {}, // 在绑定元素的父组件 // 及他自己的所有子节点都挂载完成后调用 mounted(el, binding, vnode, prevVnode) {}, // 绑定元素的父组件更新前调用 beforeUpdate(el, binding, vnode, prevVnode) {}, // 在绑定元素的父组件 // 及他自己的所有子节点都更新后调用 updated(el, binding, vnode, prevVnode) {}, // 绑定元素的父组件卸载前调用 beforeUnmount(el, binding, vnode, prevVnode) {}, // 绑定元素的父组件卸载后调用 unmounted(el, binding, vnode, prevVnode) {} }
v-model本质上是一个语法糖。
v-model其实就是 :value和@input事件的简写。
定于数据角度对比:
ref 用来定义:基本类型数据
reactive 用来定义:对象、或数组类型的数据
备注:ref也可以用来定义对象或数组类型数据,它内部会自动通过reactive
转为代理对象
原理角度对比:
ref 通过Object.defineProperty()
的 get 与 set 来实现响应式的(数据劫持)
reactive 通过使用Proxy
来实现响应式(数据劫持),并通过Reflect 操作源对象内部的数据。
使用角度对比:
ref 定义的数据:操作数据需要.value
,读取数据时模版中直接读取不需要.value
reactive 定义的数据:操作数据与读取数据,均不需要.value
toRef():
可以将值、refs 或 getters 规范化为 refs (3.3+)。
也可以基于响应式对象上的一个属性,创建一个对应的 ref。这样创建的 ref 与其源属性保持同步:改变源属性的值将更新 ref 的值,反之亦然。
toRefs():
将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。
当从组合式函数中返回响应式对象时,
toRefs
相当有用。使用它,消费者组件可以解构/展开返回的对象而不会失去响应性。
toRefs
在调用时只会为源对象上可以枚举的属性创建 ref。如果要为可能还不存在的属性创建 ref,请改用 toRef。
vue 更新 DOM 是异步更新的,数据变化,DOM 的更新不会马上完成,nextTick 的回调是在下次 DOM 更新循环结束之后执行的延迟回调。
作用:组件css作用域,避免子组件内部的css样式被父组件覆盖。
原理:给元素添加一个自定义属性 v-data-xxxxx, 通过属性选择题来提高css权重值。
相同点:
- 都是钩子函数(回调函数的一种,到某个时机了自动触发)
- 都是起到拦截作用
不同点:
- 功能不同 :axios拦截器拦截网络请求, 导航守卫拦截路由跳转
- 应用场景不同 :
- axios拦截器一般用于发送token
- 导航守卫用于页面跳转权限管理(有的页面可以无条件跳转,例如登录注册页可以无条件跳转。有的页面需要满足条件才能跳转,例如购物车页面就需要用户登录才可以跳转)
SSR也就是服务端渲染,
也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端
。
优点:
- 更好的 SEO: 因为 SPA 页面的内容是通过 Ajax 获取,而搜索引擎爬取工具并不会等待 Ajax 异步完成后再抓取页面内容,所以在 SPA 中是抓取不到页面通过 Ajax 获取到的内容;而 SSR 是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面;
- 更快的内容到达时间(首屏加载更快): SPA 会等待所有 Vue 编译后的 js 文件都下载完成后,才开始进行页面的渲染,文件下载等需要一定的时间等,所以首屏渲染需要一定的时间;SSR 直接由服务端渲染好页面直接返回显示,无需等待下载 js 文件及再去渲染等,所以 SSR 有更快的内容到达时间;
缺点:
- 更多的开发条件限制: 例如服务端渲染只支持 beforCreate 和 created 两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务端渲染应用程序中运行;并且与可以部署在任何静态文件服务器上的完全静态单页面应用程序 SPA 不同,服务端渲染应用程序,需要处于 Node.js server 运行环境;
- 更多的服务器负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用CPU 资源 (CPU-intensive - CPU 密集),因此如果你预料在高流量环境 ( high traffic ) 下使用,请准备相应的服务器负载,并明智地采用缓存策略。
<Teleport>
是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。
<Suspense>
是一个内置组件,用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态。(等待异步组件时渲染一些额外内容)
⽤ timeline ⼯具。 通过 timeline 来查看每个函数的调⽤时常,定位出哪个函数的问题,从⽽能判断哪个组件出了问题。
代码层面的优化:
- v-if 和 v-show 区分使用场景
- computed 和 watch 区分使用场景
- v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
- 长列表性能优化
- 事件的销毁
- 图片资源懒加载
- 路由懒加载
- 第三方插件的按需引入
- 优化无限列表性能
- 服务端渲染 SSR or 预渲染
SEO 优化 :
- 预渲染
- 服务端渲染 SSR
用户体验:
- 骨架屏
- PWA
Webpack 层面的优化:
- Webpack 对图片进行压缩
- 减少 ES6 转为 ES5 的冗余代码
- 提取公共代码
- 模板预编译
- 提取组件的 CSS
- 优化 SourceMap
- 构建结果输出分析
- Vue 项目的编译优化
基础的 Web 技术的优化:
- 开启 gzip 压缩
- 浏览器缓存
- CDN 的使用
- 使用 Chrome Performance 查找性能瓶颈
- 请求优化:CDN 将第三方的类库放到 CDN 上,能够大幅度减少生产环境中的项目体积,另外 CDN 能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。
- 缓存:将长时间不会改变的第三方类库或者静态资源设置为强缓存,将 max-age 设置为一个非常长的时间,再将访问路径加上哈希达到哈希值变了以后保证获取到最新资源,好的缓存策略有助于减轻服务器的压力,并且显著的提升用户的体验
- gzip:开启 gzip 压缩,通常开启 gzip 压缩能够有效的缩小传输资源的大小。
http2:如果系统首屏同一时间需要加载的静态资源非常多,但是浏览器对同域名的 tcp 连接数量是有限制的(chrome 为 6 个)超过规定数量的 tcp 连接,则必须要等到之前的请求收到响应后才能继续发送,而 http2 则可以在多个 tcp 连接中并发多个请求没有限制,在一些网络较差的环境开启 http2 性能提升尤为明显。
- 懒加载:当 url 匹配到相应的路径时,通过 import 动态加载页面组件,这样首屏的代码量会大幅减少,webpack 会把动态加载的页面组件分离成单独的一个 chunk.js 文件
- 预渲染:由于浏览器在渲染出页面之前,需要先加载和解析相应的 html、css 和 js 文件,为此会有一段白屏的时间,可以添加loading,或者骨架屏幕尽可能的减少白屏对用户的影响体积优化
- 合理使用第三方库:对于一些第三方 ui 框架、类库,尽量使用按需加载,减少打包体积
- 使用可视化工具分析打包后的模块体积:webpack-bundle- analyzer 这个插件在每次打包后能够更加直观的分析打包后模块的体积,再对其中比较大的模块进行优化
- 提高代码使用率:利用代码分割,将脚本中无需立即调用的代码在代码构建时转变为异步加载的过程
- 封装:构建良好的项目架构,按照项目需求就行全局组件,插件,过滤器,指令,utils 等做一 些公共封装,可以有效减少我们的代码量,而且更容易维护资源优化
- 图片懒加载:使用图片懒加载可以优化同一时间减少 http 请求开销,避免显示图片导致的画面抖动,提高用户体验
- 使用 svg 图标:相对于用一张图片来表示图标,svg 拥有更好的图片质量,体积更小,并且不需要开启额外的 http 请求
1. 底层的语言
webpack
是基于nodejs
构建,JavaScript 是以毫秒计数。vite
是基于esbulid
预构建依赖,esbulid
是采用go
语言编写的,go
语言是纳秒级别的。2. 打包过程
webpack
:分析各个模块之间的依赖=>然后进行编译打=>打包后的代码在本地服务器渲染。随着模块增多,打包的体积变大,造成热更新速度变慢。vite
:启动服务器=>请求模块时按需动态编译显示。vite:
- 开发环境:基于 原生 ES 模块(Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。)
- 生产环境:使用 Rollup 打包
3. 配置方式
webpack配置复杂,需要配置各种loader、plugin。
Vite配置简单,基于 Rollup,大多数功能开箱即用。
4. TypeScript支持
webpack需要额外的loader来处理TypeScript。
Vite内置了对TypeScript的支持。
5. 生态系统
- webpack的生态更加丰富成熟。
- Vite作为较新方案,生态还在快速发展中。
6. 总结
Vite具有更快的启动速度、轻量的配置、更好的HMR和SSR支持等特点,适合现代化的框架。但它也存在部分生态缺失的问题。Webpack具有更全面的生态和插件支持,但配置复杂,构建速度较慢。不同场景下可根据需求选择不同的工具。
//path模块是node.js中处理路径的核心模块。可以方便的处理关于文件路径的问题。 //path路径参数 const path = require('path') //解析和转换.vue文件,提取出其中的逻辑代码script,样式代码style以及HTML模板template, 再分别将它们交给对应的loader去处理。 //使用vue-loader@15以上都需要使用vueloaderplugin这个插件 const VueLoaderPlugin = require('vue-loader/lib/plugin'); //html-webpack-plugin插件 生成的内存中的页面已帮我们创建并正确引用了打包编译生成的js及css文件 const htmlWebpackPlugin = require('html-webpack-plugin'); //mini-css-extract-plugin 插件是 webpack4+ 版本的,可以直接安装使用。 这里只能把所有样式包括css、less都打包到一个css文件,然后再 link 进页面。 const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //性能分析页面工具 const BundleAnalyzerPlugins = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
XSS
称为 跨站脚本攻击。
- 攻击者在目标网站上注入恶意代码,当用户浏览目标网站时,浏览器会渲染整个
HTML
文档,这个过程中出现了不被预期的脚本指令,并且被浏览器执行了,XSS
就会发生。- 利用这些恶意代码,攻击者可以获取用户的敏感信息如
Cookie
、sessionId
等,控制用户的账号权限,进而危害数据安全。
防范:
- 转义HTML
- 关注高危API
- Content Security Policy(内容安全策略,简称
csp
)
- 用于检测并阻止网页加载非法资源的安全策略,可以减轻
xss
攻击带来的危害和数据注入等攻击。
- 开启http only
禁止
JavaScript
读取某些敏感Cookie
,攻击者完成XSS
注入后也无法窃取此Cookie
。
CSRF攻击指的是跨站请求伪造。
攻击者诱导用户进入第三方网站,然后该网站向被攻击网站发送跨域请求。
如果用户在被攻击的网站中保存了登录状态,那么攻击者就会利用这个登录状态,绕过后台的用户验证,冒充用户向服务器执行一些操作。
本质:
利用了Cookie会在同源请求中携带发送给服务器的特点,以此来实现用户的冒充
防范:
- 同源检测
- Token
- 双重Cookie验证
- 在设置Cookie属性的时候设置Samesite
1xx(临时响应)
表示临时响应并需要请求者继续执行操作的状态代码。
- 100 (继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
- 101 (切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。
2xx (成功)
表示成功处理了请求的状态代码。
- 200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
- 201 (已创建) 请求成功并且服务器创建了新的资源。
- 202 (已接受) 服务器已接受请求,但尚未处理。
- 203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。
- 204 (无内容) 服务器成功处理了请求,但没有返回任何内容。
- 205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。
- 206 (部分内容) 服务器成功处理了部分 GET 请求
3xx (重定向)
表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
- 300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
- 301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
- 302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
- 303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
- 304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
- 305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
- 307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
4xx(请求错误)
这些状态代码表示请求可能出错,妨碍了服务器的处理。
- 400 (错误请求) 服务器不理解请求的语法。
- 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
- 403 (禁止) 服务器拒绝请求。
- 404 (未找到) 服务器找不到请求的网页。
- 405 (方法禁用) 禁用请求中指定的方法。
- 406 (不接受) 无法使用请求的内容特性响应请求的网页。
- 407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
- 408 (请求超时) 服务器等候请求时发生超时。
5xx(服务器错误)
这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
- 500 (服务器内部错误) 服务器遇到错误,无法完成请求。
- 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
- 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
- 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
- 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
- 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。