赞
踩
v-show通过css 的 display属性控制显示和隐藏,v-if 是创建和销毁,而不是显示和隐藏,频繁切换状态使用 v-show 否则 v-if,现在大多不用考虑性能问题,所以一般可以使用v-if
快速查找到节点,减少渲染次数,提升渲染性能,防止渲染时因为dom结构顺序改变,出现渲染错误
组件的生命周期 指的是:组件从 创建 -> 运行(渲染) -> 销毁 的整个过程,强调的是一个 时间段
在组件的生命周期中,vue框架为组件内置了不同时刻的生命周期函数,生命周期函数会在组件运行的过程中自动调用,单组件生命周期函数有一下几种:
beforeCreate
: 组件实例刚刚被创建,属性和方法还未初始化。
created
: 组件实例被创建,属性和方法已经初始化,但是 DOM 还未渲染。
可以在该节点进行数据的操作,比如发起请求获取数据
beforeMount
: 组件初次被渲染到页面之前。
mounted
: 组件被渲染到页面之后。
可以在该节点,获取并操作dom结构。
beforeUpdate
: 组件更新前触发。
updated
: 组件更新后触发。
beforeUnmount
: 组件卸载前触发。
unmounted
: 组件卸载后触发。
做一些清理性质的工作,如事件解绑,定时器清除
父子组件生命周期图
挂载: parent beforeCreate => parent created => parent beforeMount => child beforeCreate => child created => child beforeMount => child mounted => parent mounted
更新: parent beforeUpdate => child beforeUpdate => child updated => parent updated
销毁: parent beforeDestroy => child beforeDestroy => child destroyed => parent destroyed
从以上能够看出:
挂载时,子组件是在父组件before mount后开始挂载,并且子组件先mounted,父组件随后
更新时,子组件是在父组件before update后开始更新,子组件先于父组件更新
销毁时,子组件是在父组件before destroy后开始销毁,并且是子组件先销毁,父组件随后。
或者叫组件之间如何通信
组件之间的数据传递一共有六种方式。
1、父组件向子组件通过自定义属性传递参数
2、子组件向父组件通过自定义事件传递参数
3、父子组件使用 v-model指令进行进行双向数据绑定
4、兄弟组件之间通过 EventBus 进行传参
5、祖先组件向后代组件的传参,比如父组件通过 provide 方法将数据共享给子孙组件,子孙组件使用 inject数组进行接收。
6、vuex
(详细使用见 vue3 部分笔记)
需要注意的是,在执行更新函数时,Vue 会对计算新的 VNode 进行优化,以提高渲染性能。其中,一个重要的优化手段是使用虚拟 DOM(Virtual DOM),通过比对新旧虚拟 DOM,避免不必要的 DOM 操作,减少了渲染的开销。
假设我们有一个 message
数据属性和一个输入框,我们希望在输入框中输入内容时,message
数据属性也会实时更新,而当修改 message
数据属性时,输入框中的值也会实时更新。我们可以使用 v-model
来实现这个功能。其功能在vue中的实现原理如下:
message
数据属性上。这个步骤相当于给输入框添加了一个 value
属性,这个属性的值等于 message
数据属性的值。同时,Vue 会监听输入框的 input
事件,当事件被触发时,会将输入框的值更新到 message
数据属性中。
这样,当我们在输入框中输入内容时,message
数据属性也会实时更新。
message
数据属性的变化绑定到输入框的值上。这个步骤相当于给输入框添加了一个 input
事件监听器,当 message
数据属性发生变化时,输入框的值也会自动更新。具体来说,当 message
数据属性的值发生变化时,Vue 会将新的值设置为输入框的 value
属性,从而实现输入框的实时更新。
MVVM 是一种架构模式,全称为 Model-View-ViewModel
model:模型;view:视图;viewmodel:视图模型
核心是 viewmodel视图模型
视图模型是一个vue实例,负责将视图与数据模型进行双向绑定。当数据发生变化时,会自动更新视图。也就是数据驱动视图。而当用户操作视图时,ViewModel 也会自动更新数据模型。
总之,在 Vue 中,采用 MVVM 架构模式,通过 ViewModel 来实现数据双向绑定,让开发者只需关注数据模型的变化,而无需手动操作 DOM,提高了开发效率。同时,也使得应用程序更加易于维护和扩展。
计算属性, 能够缓存数据,如果数据不变,不会重新计算。能够提高性能。
什么是组件:在 Vue 中,组件(Component)是可复用的、独立的模块,用于构建用户界面。一个组件可以包含模板、脚本、样式等内容,可以接受外部传入的数据,同时也可以向外部发送事件。
如何封装组件:在实际开发中,我们可以根据业务需求,将一些通用的 UI 组件、业务组件等进行封装,提高代码复用性。
为什么要封装组件:减少重复代码的编写,提升开发效率和代码的可维护性。
data 为什是一个函数:因为组件是可以复用的,多次使用同一个组件,每个实例都需要有自己的数据,如果定义为对象,所有实例共享一个数据对象,一个实例的数据变化便会影响到其他实例。定义成一个函数,每次使用组件时都会调用该函数返回一个新的数据对象。保证每个实例都有独立的数据。
使用mixin 对公共部分的逻辑进行抽离,Mixin 是一种可重用的对象,可以包含一些组件中常用的逻辑和数据,然后将其混合到一个或多个组件中去。Mixin 可以用来在多个组件中共享代码,从而避免重复的代码,提高代码复用性和可维护性。
缓存组件
做一些清理性质的工作时,如 解绑事件、清除定时器
在使用插槽的时候可以利用插槽传输数据,绑定了自定义数据的插槽叫做作用域插槽,使用的时候在插槽的名字后面使用等号进行数据的接收。
vuex 是一个专门为 vue 构建的状态管理工具,主要是为了解决 多组间之间状态共享问题。强调的是集中式管理,(组件与组件之间的关系变成了组件与仓库之间的关系)
核心概念如下:
state:数据源
Mutations:在该节点中定义方法操作 state 中的数据
Action:处理异步任务
Getter:类似与计算属性,对state中的数据进行加工处理,不会修改到state节点中的数据
默认是 哈希模式(Hash mode)、第二种是 历史模式(History mode)需要后台服务器的支持
在Vue.js中,我们可以通过Webpack的代码分割功能(Code Splitting)来实现路由组件的异步加载。异步加载可以提高应用程序的性能,因为它可以延迟加载不需要立即显示的路由组件,而只在需要时才加载它们。
要实现路由组件的异步加载,可以使用Webpack的动态import语法,如下所示:
const Foo = () => import('./Foo.vue')
上面的代码使用箭头函数和import()语法来异步加载Foo.vue组件
接下来,我们可以在Vue Router的路由配置中使用这个异步加载的组件:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{
path: '/foo',
component: () => import('./Foo.vue')
}
]
})
上面的代码中,我们使用箭头函数和import()语法来异步加载Foo.vue组件,并将其作为路由组件的component选项。
如果是vue.js 2x 还需要进行一些额外的配置。
vue中的watch监听数据变化
Vue 的响应式原理是通过利用 ES5 中的 Object.defineProperty()
方法来实现的。
当 Vue 初始化时,它会对 data
对象中的每个属性进行递归地遍历,并使用 Object.defineProperty()
将这些属性全部转换为 getter 和 setter。这样,当组件实例的数据发生变化时,就会自动触发 setter 函数,并通知依赖于该属性的所有组件进行重新渲染。
具体来说,当访问组件实例的一个属性时,例如 this.message
,Vue 会通过 getter 方法进行拦截,并返回该属性的值。在同一个组件实例的模板中,如果使用了 {{ message }}
的语法,则 Vue 会自动将这个模板渲染函数添加到该属性的依赖列表中。当该属性的值发生变化时,Vue 就会通过 setter 方法进行拦截,并通知所有依赖于该属性的组件进行重新渲染。
这种基于 getter 和 setter 的响应式原理是 Vue 实现数据绑定和视图更新的核心机制。由于它只需要对每个属性进行一次遍历和转换,因此对于大规模的应用程序来说,它具有很高的性能和可维护性。
除了 Object.defineProperty()
方法,Vue 3 中还引入了新的响应式系统,它是基于 ES6 的 Proxy 对象实现的,相比于 Object.defineProperty()
,它具有更好的性能和可扩展性,同时支持对 Map、Set 和 WeakMap 等数据结构的响应式处理。
Vue 采用异步渲染的主要原因是为了提高渲染效率和性能。当 Vue 组件更新时,它会触发一系列的操作,包括重新计算虚拟 DOM 树、比较新旧虚拟 DOM 树的差异、更新实际 DOM 树等等,这些操作可能会消耗大量的时间和计算资源。为了避免这些操作对应用程序的响应性产生影响,Vue 采用了异步渲染的策略,将这些操作放在事件循环的下一个 tick 中执行,使得组件更新不会阻塞主线程,提高了用户体验。
在 Vue 中,$nextTick
方法是用来在下一个 tick 中执行一个回调函数的,该回调函数会在当前组件更新完成后被执行。由于 Vue 采用了异步渲染的策略,因此在某些情况下,如果我们想要在组件更新完成后执行一些操作,就需要使用 $nextTick
方法来确保这些操作能够正确地执行。例如,在组件的 mounted 钩子函数中,我们可能需要获取组件的实际 DOM 元素的尺寸或位置等信息,这些信息只有在组件更新完成后才能够正确地获取,因此我们需要在 $nextTick
回调函数中执行这些操作。
下面是一个示例代码,演示了如何使用 $nextTick 方法:
export default { data() { return { message: 'Hello, world!', width: 0, height: 0 } }, mounted() { // 获取组件的实际宽度和高度 this.$nextTick(() => { const el = this.$el this.width = el.offsetWidth this.height = el.offsetHeight }) } }
再通俗的解释一下这里的 tick 表示什么意思,为什么叫 tick?
在计算机中,tick 表示系统的一个基本时间单位,通常等于几十毫秒或几毫秒。每个 tick 的时间长度取决于操作系统和硬件平台,不同的系统和平台可能有不同的定义。在 JavaScript 中,tick 的含义稍有不同,通常表示 JavaScript 引擎中一次完整的事件循环(event loop)周期,也就是说,一次 tick 表示 JavaScript 引擎处理完所有当前存在的任务,然后开始处理下一轮异步任务的过程。
在 Vue 中,异步任务一般是在下一个 tick 执行的,这意味着当一个组件的数据发生变化时,Vue 并不会立即更新视图,而是在当前的 tick 结束后才会进行更新。这样做的好处是可以避免频繁地更新视图,提高渲染效率和性能,同时还可以避免一些常见的问题,比如数据更新时视图更新不同步、事件处理函数不立即响应等。
因此,Vue 中的 tick 具体指的是 JavaScript 引擎中的一次完整事件循环周期,通常表示在当前 tick 结束后执行的下一轮异步任务。通过将组件更新操作放在下一个 tick 中执行,Vue 实现了高效的异步渲染机制,保证了组件的渲染效率和性能。
1、使用 v-if 和 v-for 指令时需要注意:
不要同时使用 v-if 和 v-for,因为它们的优先级不同,同时使用可能导致性能问题。
在使用 v-for 时,需要设置唯一的 key 值来提高性能。
2、使用 computed 属性或 watch 监听器来监听数据变化,以避免不必要的渲染和计算。
3、对于一些静态组件或内容,可以使用 v-once 指令(标记某个元素或组件只渲染一次)来进行缓存,以避免重复渲染。
4、使用异步组件来延迟加载页面,提高首屏加载速度。
5、对于一些长列表或大数据集合,可以使用虚拟滚动或分页加载等技术来优化性能,避免一次性加载大量数据。
6、使用 Webpack等工具进行代码压缩和打包,以减小文件体积和加载时间。
7、前端通用的性能优化措施:如图片的懒加载、减少HTTP的请求次数等。
数据驱动和组件化
1.直接在子组件中通过this.$parent.event来调用父组件的方法。
<template>
<button @click="handleClick">调用父组件方法</button>
</template>
<script>
export default {
methods: {
handleClick() {
this.$parent.handleCustomEvent()//调用父组件中的方法
}
}
}
</script>
2.在子组件里用$emit向父组件触发一个事件,父组件监听这个事件就行了。
3.父组件使用 provide 把方法传入子组件中,在子组件里通过inject接收并直接调用这个方法。
① 父组件向子组件通过 provide 传递数据或方法
<template> <div> <child-component></child-component> </div> </template> <script> export default { provide: { parentMethod: this.handleCustomEvent }, methods: { handleCustomEvent() { // 父组件中的方法逻辑 } } } </script>
② 在子组件中通过 inject
注入父组件中提供的数据或方法
<template>
<button @click="handleClick">调用父组件方法</button>
</template>
<script>
export default {
inject: ['parentMethod'],
methods: {
handleClick() {
this.parentMethod()
}
}
}
</script>
通过 ref 引用获取子组件的实例,通过该实例直接调用子组件中的方法。
1.使用vue-router通过跳转链接带参数传参。
2.使用本地缓存localStorge。
3.使用vuex数据管理传值
多个组件通过同一个挂载点进行组件的切换,is的值是哪个组件的名称,那么页面就会显示哪个组件。
$route
和 $router
的区别是什么?$router为VueRouter的实例,是一个全局路由对象,包含了路由跳转的方法、钩子函数等。
$route 是路由信息对象。每一个路由都会有一个route对象,是一个局部对象,包含path,params,hash,query,fullPath,matched,name等路由信息参数。
push() pop() shift() unshift() splice() sort() reverse() vue数组对象修改触发视图更新
keep-alive缓存vue实例,提高性能是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。
在 Vue 中,computed、watch、methods 都是用于处理数据逻辑的方法,但它们之间的区别如下:
computed:计算属性是一个基于响应式依赖进行缓存的属性。当其依赖的数据发生变化时,计算属性会重新计算,并将计算结果缓存起来,直到其依赖的数据再次发生变化。计算属性适用于依赖其他数据进行计算的场景。
watch:是一个监听数据变化并执行回调函数的方法。可以通过 watch 方法监听一个数据的变化,并在数据变化时执行相应的回调函数。适用于监听某个数据的变化并作出相应的响应,例如异步请求数据。
methods:方法是一段可以执行的代码块,可以在模板或其他方法中调用。方法适用于需要执行一些逻辑的场景,例如点击事件处理函数、表单提交处理函数等。
vue是异步渲染的框架,data改变之后,dom不会立刻渲染,$nextTick会在dom渲染之后被触发,以获取最新dom节点
获取dom元素,或者是获取子组件的实例。使用:this.$refs.自定义的引用名称
1、动态路由传参:在路由定义时使用冒号(:)来定义动态参数,例如:
{
path: '/user/:userId',
component: User
}
在组件内可以通过 $route.params
来访问动态路由参数:
export default {
mounted() {
const userId = this.$route.params.userId
// 对 userId 进行操作
}
}
2、查询参数传参:在路由中使用查询字符串(?)来定义参数,例如
{
path: '/user?userId=1',
component: User
}
在组件内可以通过 $route.query
来访问查询参数:
export default {
mounted() {
const userId = this.$route.query.userId
// 对 userId 进行操作
}
}
3、路由元信息传参:在路由定义时可以添加一些额外的元信息来传递参数,例如:
{
path: '/user',
component: User,
meta: {
userId: 123
}
}
在组件内可以通过 $route.meta
来访问路由元信息:
export default {
mounted() {
const userId = this.$route.meta.userId
// 对 userId 进行操作
}
}
4、编程式导航传参:使用 router.push()
方法进行编程式导航时,可以在第二个参数中传递参数,例如:
this.$router.push({ path: '/user', query: { userId: 123 }})
在组件内可以通过 $route.query
来访问传递的参数。
Axios是一个基于 promise 的专注于实现网络数据请求的 HTTP 库
axios拦截器可以实现对请求和响应的全局拦截和处理,包括请求拦截器(在请求发出之前进行拦截处理)和响应拦截器(在响应接收前进行拦截处理)
请求拦截器:axios.interceptors.request.use()
响应拦截器:axios.interceptors.response.use()
拦截器中可以做一些操作,比如添加一个加载样式,对请求头进行一些配置等。
在项目中配置 proxy代理(在开发调试阶段使用),在服务器端配置 cors 跨域资源共享
首屏时间的快与慢,直接影响到了用户对网站的认知度。所以首屏时间的长短对于用户的滞留时间的长短、用户转化率都尤为重要。
在 Vue 项目中,可以采取以下几种方式来进行首屏优化:
按需引入第三方库:Vue 项目中引入第三方库时,一定要注意只引入需要使用的部分,减少无用的代码和文件体积,可以通过 Tree shaking 或按需引入来实现。
代码分割和按需加载:将项目代码分割成多个小模块,按需加载,而不是一次性加载所有的代码,可以大幅度减少首屏加载时间,提升用户体验。Vue CLI 中默认使用了 code-splitting 技术。
使用缓存:合理利用浏览器缓存,缓存公共文件和静态资源文件,可以减少服务器的请求次数,提升页面加载速度。
图片懒加载:在 Vue 项目中使用图片懒加载技术,只有在用户滚动到图片位置时才加载图片,而不是一次性加载所有图片,可以加速首屏加载时间,提升用户体验。
服务端渲染(SSR):使用 SSR 技术可以让用户在请求页面时,就直接从服务器获取已经渲染好的 HTML 文件,提升首屏渲染速度。Vue 官方提供了 Vue SSR 框架。
优化代码:Vue 项目中代码优化也是重要的一环,优化代码结构,减少重复代码,使用 Vue 内置的优化指令和组件,减少页面的计算量和重新渲染次数,可以提升页面性能和响应速度。
.stop - 调用 event.stopPropagation(),禁止事件冒泡。
.prevent - 调用 event.preventDefault(),阻止事件默认行为。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
v-model 指令常用修饰符:
.number - 输入字符串转为数字
.trim - 输入首尾空格过滤
.lazy-绑定之后数据延迟更新,比如输入框,不使用该修饰符的时候,输入框中的内容只要一改变就会立马更新data中的数据(比如数据为 message )。加上该修饰符后,当输入框失去焦点后才会同步数据。
在监听键盘事件时,我们经常需要判断用户按下的是哪一个按键。此时,可以为键盘相关的事件添加按键修饰符,例如:
<input @keyup.enter="submit">
Vue的单页面应用程序(Single Page Application,SPA)指的是在一个页面内使用Vue进行动态渲染,以实现前端路由、组件化等特性的Web应用程序。与传统的多页面应用程序相比,Vue的单页面应用程序有以下优缺点:
优点:
更快的页面切换:因为Vue的单页面应用程序只在初始化时加载一次,之后只需要加载必要的数据和组件,所以在页面切换时不需要重新加载整个页面,从而实现更快的页面切换。
更好的用户体验:Vue的单页面应用程序可以实现更流畅、更快速的用户体验,因为在切换页面时不需要重新加载整个页面,而是只需要切换组件,从而减少了页面的闪烁和卡顿现象。
更高的开发效率:Vue的单页面应用程序使用组件化的开发方式,可以将整个应用程序拆分成多个组件,每个组件都可以独立开发、测试和调试,从而提高了开发效率和代码质量。
缺点:
初次加载时间长:因为Vue的单页面应用程序需要加载所有必要的组件和数据,所以初次加载时间会比较长,特别是对于一些复杂的应用程序来说,需要加载的内容更多,加载时间更长。
对浏览器的兼容性要求高:Vue的单页面应用程序需要使用一些新的浏览器技术,比如HTML5、CSS3、ES6等等,所以对浏览器的兼容性要求比较高,对一些低版本的浏览器可能无法兼容。
不利于SEO优化:尽管Vue的单页面应用程序可以实现更好的SEO优化,但是对于一些需要SEO优化的应用程序来说,可能还需要额外的SEO优化工作,比如使用预渲染技术等等,从而提高网站在搜索引擎上的排名。
DNS解析:浏览器根据URL中的域名,通过DNS解析获取服务器的IP地址。
建立TCP连接:浏览器与服务器建立TCP连接。这个过程涉及到TCP协议中的三次握手,确保客户端与服务器之间的连接稳定可靠。
发送HTTP请求:浏览器向服务器发送HTTP请求。获取服务器端的资源。
服务器响应:客户端获取到资源
TCP四次挥手关闭客户端和服务器的连接
浏览器解析文档资源并渲染页面
浏览器解析文档资源并渲染页面流程:
(1)解析html资源,构建DOM Tree
(2)解析css资源,构建CSS Rule Tree
(3)JS通过DOM API和CSSOM API来操作DOM Tree和CSS Tree
(4)解析完成后综合DOM Tree和CSS Tree会生成Render Tree,计算每个元素的位置,这个过程就是回流(layout or reflow)
(5)调用操作系统Native GUI的绘制
(6)页面绘制完成
TCP建立连接的三次握手:
客户端发送 SYN 包:客户端向服务器发送一个 SYN(同步)包,表示客户端请求连接。该包中包含一个随机生成的序列号 A。
服务器发送 SYN+ACK 包:服务器接收到 SYN 包后,向客户端回送一个 SYN+ACK(同步+确认)包。该包中包含服务器随机生成的序列号 B,以及确认号 A+1(表示客户端的 SYN 包已经收到)。此时,服务器进入 SYN_RCVD 状态,等待客户端的确认。
客户端发送 ACK 包:客户端收到 SYN+ACK 包后,向服务器发送一个 ACK(确认)包。该包中包含客户端确认号 B+1(表示服务器的 SYN+ACK 包已经收到)。此时,客户端进入 ESTABLISHED(已连接)状态,服务器收到该包后也进入 ESTABLISHED 状态,此时连接建立成功。
简单理解:① 客户端向服务器发送一个请求包;② 服务器收到后向客户端发送一个包表示收到,③ 客户端收到后返回一个确认包,表示知道服务器端收到了
客户端:请求链接
服务器:知道了
客户端:我知道你知道了
TCP断开链接的四次挥手:
TCP四次挥手是TCP连接的关闭过程,由连接的任何一方都可以发起。四次挥手过程如下:
主动关闭方发送FIN包:当客户端决定关闭连接时,它向服务器发送一个FIN包,表示它不会再向服务器发送数据。
被动关闭方发送ACK包:服务器收到客户端发送的FIN包后,发送一个ACK包,表示已经收到客户端发来的FIN包,并确认该包中的序列号。
被动关闭方发送FIN包:当服务器也准备关闭连接时,它向客户端发送一个FIN包,表示它不会再向客户端发送数据。
主动关闭方发送ACK包:客户端收到服务器发送的FIN包后,向服务器发送一个ACK包,表示已经收到服务器发来的FIN包,并确认该包中的序列号。
简单理解,比如客户端主动发送断开链接请求
客户端:不要数据了(不再向服务器发送数据)
服务器:收到
服务器:准备断开链接 (不再向客户端发送数据)
客户端:了解,over!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。