vue2
vue2
1、data 为什么是一个函数
data
函数如下:
<script>
module.exports = {
data() {
return {
text: 123;
}
}
}
</script>
vue 中的组件是用来复用的,为了防止我们多次使用同一个组件时,这个组件中的data
被复用,即我们每次访问的都是同一个data
,因此将其定义为一个函数。这样我们每次使用组件时,它里面的data
数据都是相互隔离互不影响的。
2、v-if和v-show
它们都可以控制元素的显示和隐藏
- v-show:使用
display: none
来让元素隐藏 - v-if:将元素删除或者添加进来到文档来控制显隐
v-if有一个局部编译/卸载的过程,切换这个过程中会适当的销毁和重建内部的事件监听和子组件,会触发组件的生命周期,切换效率更低。
v-show只是简单的css切换,不会触发组件的生命周期,切换效率更高。
3、v-for中的key值的作用
key属性是DOM元素的唯一标识,在页面的DOM改动时,vue会根据key去判断哪些元素是新增的,哪些是不变的,这样就能更高效的改动DOM树。
4、vue的生命周期
- 创建:
- beforeCreate:这个阶段,属性和方法都不能使用
- created:这个阶段是实例创建完成后,这里完成了数据监测,可以使用数据,修改数据,不会触发updated,也不会更新视图
- 挂载
- beforeMount:这里完成了模板的编译,虚拟DOM也完成创建,即将渲染,可以修改数据,不会触发updaed
- mounted:将编译好的模板挂载到页面上,这里可以发送异步请求,也可以访问DOM节点
- 更新
- beforeUpdate:组件数据更新前使用,数据是新的,页面上的数据是旧的,组件即将更新,准备渲染,可以修改数据
- updated:render重新做了渲染,这时数据和页面都是新的,避免再此更新数据
- 销毁
- beforeDestroy:实例销毁前,在这里实例还可以使用,可以清除定时器等等
- destroyed:组件已经被销毁
- 使用了keep-alive:
- activated:组件激活时
- deactivated:组件被销毁时
5、在created和mounted去请求数据有什么区别
created:在渲染前调用,通常先初始化属性,然后做渲染。在这里请求数据不会造成闪屏问题,因为此时页面还未挂载到屏幕中。
mounted:在模板渲染完成后调用,一般都是初始化页面后,再对元素节点进行操作。在这里请求数据可能会出现闪屏的问题,这是由于加载时机不对造成的。
一般在created中请求数据较多。
可以理解为:如果请求的数据对DOM有影响,则使用created,如果与DOM无关,则可以使用mounted。
6、vue中的修饰符
- 事件修饰符
- .stop:阻止冒泡
- .prevent:阻止默认行为
- .capture:内部元素触发事件先在此处理
- .self:只有在event.target是当前元素时触发
- .once:事件只触发一次
- .passive:立即触发默认行为
- .native:把当前元素作为原生标签看待
- 按键修饰符
- .keyup:按键抬起
- .keydown:按键按下
- 系统修饰符
- .ctrl
- .alt
- .meta
- 鼠标修饰符
- .left:鼠标左键
- .right:鼠标右键
- .middle:鼠标中间
- 表单修饰符
- .lazy:等输入完之后再显示
- .trim:删除内容前后的空格
- .number:输入数字,或者将输入内容转为数字
7、vue中的组件通信
- 父传子:
- props
- $ref
- 子传父:
- $emit
- 兄弟之间:
- 事件总线 bus
- vuex传值
- provide/inject:允许一个祖先组件向其所有的子孙组件传递数据,不管层级多深,这个子孙组件都能直接使用祖先组件传递的数据/方法。
8、keep-alive
keep-alive是Vue的一个内置组件,包裹组件时,会缓存不活跃的组件实例,而不是直接销毁它们。
作用:把组件切换的状态保存在内存中,防止重复渲染DOM节点,减少加载时间和性能消耗,提升用户体验。
9、axios是怎么做封装的
10、vue路由传参
params传参
this.$router.push({name: "index", params: {id: 123}}) // 传递参数 this.$route.params.id // 获取传递的参数
路由属性传参
this.$router.push({name: `/index/${id}`}) // 传递参数,它需要在路由配置中写上需要的参数
query传参
this.$router.push({ name: "index", query: {id: 123} }) // 传递参数,它的参数在url地址中,可以解决刷新页面导致参数丢失问题
11、hash模式和history模式的区别
- hash的路由地址上有#,history没有
- 在做回车刷新时,hash会加载对应页面,history会报错404
- hash模式支持低版本浏览器,history不支持,因为是H5新增的
- hash不会重新加载页面,单页面应用必备
- history有历史记录,H5新增了pushState和replaceState两个方法去修改历史记录
- history模式需要后台配置
12、路由拦截是怎么实现的
需要在路由配置中添加一个字段,它是用于判断路由是否需要拦截的
{
name: "index",
path: "/index",
component: Index,
meta: {
requireAuth: true, // 表示当前这个路由需要拦截
}
}
// 这里的代码只是一个示例
router.beforeEach((to, from, next) => {
if(to.meta.requireAuth) {
// 需要拦截
if(store.state.token) {
// 通过token判断是否登录了
next()
} else {
// 其他操作
// ...
}
}
})
13、动态路由
在路由配置中设置meta属性,扩展权限相关的字段。在路由导航守卫中通过判断这个权限标识,实现路由的动态增加和跳转。
获取到用户登录后返回的用户角色,然后根据这个角色跟路由表中的meta中相关字段进行匹配,然后将匹配到的路由形成可访问的路由。
14、如何解决刷新后二次加载路由
window.location.reload()
matcher
const router = createRouter() export function resetRouter() { const newRouter = createRouter() router.matcher = newRouter.matcher } // 然后在 addRouter/addRoutes 之前调用一次 resetRouter resetRouter() this.$router.addRoutes(routeMenu)
如果需要删除添加一级路由下面的子路由时,可以通过
this.$router.options.routes
获取到路由数组,然后通过循环的方式进行push/splice,然后再用上面的方式进行全局替换即可。
15、vuex刷新数据会丢失吗,怎么解决
放到sessionStorage、localStorage、cookie中
页面刷新时,再次请求数据,达到可以动态更新的方法
监听浏览器的刷新事件,在刷新前把数据保存到sessionStorage里,刷新后请求数据,请求到了用vuex,如果没有则用sessionStorage里的数据
window.onbeforeunload = function() { // beforeunload:当窗口、文档及其资源即将被卸载时,触发该事件。 console.log("刷新了页面") }
16、computed和watch的区别
- computed是计算属性,watch是监听数据变化,监听的是data中的数据
- computed支持缓存,依赖的数据发生了变化才会重新计算,而watch不支持缓存
- computed不支持异步,watch支持异步操作
- computed在第一次加载时就开始监听,而watch在第一次时不监听
- computed函数中必须有return,而watch不需要
17、vue的双向数据绑定的原理
通过数据劫持和发布订阅者模式来实现的。
vue2利用Object.defineProperty()方法来劫持各个属性的getter和setter。vue3使用Proxy。在数据发生改变的时候发布消息给订阅者,触发对应的监听回调渲染视图。
数据和视图是同步的,一方发生变化都会引发另一方同步变化。
对需要observer的数据对象进行递归,包括子属性对象的属性,都添加上getter、setter
compile模板解析指令,把模板中的变量替换成数据,然后初始化渲染视图,同时把每个指令对应的节点绑定上更新函数,添加订阅者,如果数据变化,收到通知,更新视图
watcher订阅者是observer和compile之间的通信桥梁
watcher的作用:
- 在自身实例化的时候往订阅器内添加自己
- 自身要有一个update()方法
- 等待属性变动时,调用自身的update方法,触发compile中的回调
MVVM作为数据绑定的入口,整合了observer、compile、watcher三者,通过observer来监听自己的数据变化,通过compile来解析模板指令,然后利用watcher把observer和compile联系起来,最终达到数据和视图的双向绑定效果。
18、diff算法和虚拟DOM
虚拟DOM:使用js对象表示真实DOM,描述元素和元素之间的关系。如果组件内有响应式数据,数据发生改变时,render函数会生成一个新的虚拟DOM,这个新的虚拟DOM会和旧的虚拟DOM进行比对,找到需要修改的虚拟DOM内容,然后去对应的真实DOM中修改。
diff算法:新的虚拟DOM和旧的虚拟DOM比对时用的,返回一个patch对象,这个对象的作用就是存储两个节点不同的地方,最后用patch里记录的信息进行更新真实DOM。
步骤:
- js对象表示真实的DOM结构,要生成一个虚拟DOM,再用虚拟DOM构建一个真实的DOM树,渲染到页面
- 状态改变生成新的虚拟DOM,这个新的虚拟DOM跟旧的虚拟DOM进行比对,这个比对就是diff算法,利用patch记录差异
- 将记录的差异用在第一个虚拟DOM生成的真实DOM上,然后更新视图
19、vue和jquery的区别是什么
- 原理不同:vue是数据绑定视图,jquery是先获取DOM,然后处理数据与视图
- 着重点不同:vue着重于数据,是数据驱动视图;jquery是着重于页面
- 操作不同
- 未来发展不同
20、vue中遍历全局的方法有哪些
- 普通遍历:forEach()
- 对元素统一操作:map()
- 查找符合条件的元素:filter()
- 查询符合条件的元素,返回索引:findIndex()
- 遇到不符合条件的对象会停止:every()
- 找到符合条件的元素会停止:some()
21、vue的过滤器怎么使用
vue的过滤器:vue的特性,用来对文本进行格式化处理
使用它的两个地方:一个是插值表达式,一个是v-bind
分类:
全局过滤器
Vue.filter("add", function(v) { return v < 10 ? "0" + v : v }) <div>{{ 33 || add }}</div>
本地过滤器:与methods同级
filter: { add: function(v) { return v < 10 ? "0" + v : v } } <div>{{ 33 || add }}</div>
22、vue中如何做强制刷新
- location.reload()
- this.$router.go(0)
23、vue的性能优化
- 编码优化:
- 不是所有的数据都需要放在data中
- v-for时给每个元素绑定事件用事件代理
- keep-alive缓存组件
- key值要保证唯一
- 合理使用路由懒加载、异步组件
- 数据持久化存储的使用尽量用防抖节流优化
- 加载优化
- 按需加载
- 内容懒加载
- 图片懒加载
- 用户体验
- 骨架屏
- seo优化
- 预渲染
- 服务端渲染ssr
- 打包优化
- CDN形式加载第三方模块
- 多线程打包
- 抽离公共文件
- 缓存和压缩
- 客户端缓存、服务端缓存
- 服务端gzip
24、首屏优化
- 使用路由懒加载
- 非首屏组件使用异步组件
- 首屏中不重要的组件延迟加载
- 静态资源放在CDN上
- 减少首屏上js、css等资源文件的大小
- 使用服务端渲染
- 尽量减少DOM的数量和层级
- 使用精灵图请求
- 做一些loading
- 开启gzip压缩
- 图片懒加载
25、vue3的性能为什么比vue2好
diff算法的优化:
vue2中的diff算法是将虚拟DOM进行全量对比。
vue3中新增了静态标记,在与上次的虚拟DOM进行对比时,只对比带有静态标记的节点,并且可以通过标记的信息得知当前节点要对比的具体内容,如文本、class、style、props等。
静态标记只会标记会改变的节点,有些节点本身的内容本身就是写死的,因此就没有对比的必要。
静态提升:
vue2不论元素是否参与更新,每次都会重新创建,然后再渲染。
vue3对不参与更新的元素,只会做静态提升,它只被创建一次,在渲染时直接复用即可。
事件侦听缓存:
默认情况下,onClick会被视为动态绑定,所以每次都会去追踪它的变化。但是因为事件绑定的函数是同一个函数(同一个方法),所以没有追踪变化,直接缓存起来复用即可。
ssr优化:
传统的spa采用的是客户端渲染模式:vuejs构建应用程序 => webpack打包为一堆js、css资源文件,然后塞到index.html中 => 用户输入url访问页面 => 得到一个html模板页面 => 异步请求数据 => 得到服务端返会的数据 => 渲染局部页面 => 用户看到页面
这种方式必然演唱了首屏加载的时间。
ssr(服务端渲染)简单说就是将页面在服务端渲染完成后,将这些html字符串发送到浏览器,然后在浏览器中显示。这样无需等待所有的js都完成下载并执行后,才显示内容。所以用户就能更快速的看到完整渲染的页面。
26、说说对组件的理解
vue中的组件就是可以重复使用的vue实例,它有独一无二的组件名称。它可以抽离单独的公共模块,类似页面中的header、footer、list等这些有着高复用率的内容,将它们抽离出来形成一个单独的组件可以提高代码的复用率。
27、你是如何规划项目文件的
- public
- 图标、index.html、img
- src
- api
- assets
- components
- plugins
- router
- static
- styles
- utils
- views
- App.vue
- main.js
- package.json
- vue.config.js
- ...
28、是否使用过nuxt.js
nuxt.js:是基于vue的应用框架,关注的是渲染,可以开发服务端渲染应用的配置。
SSR(服务端渲染)的好处:
- ssr生成的是有内容的html页面,有利于搜索引擎的搜索
- 优化了首屏加载时间
29、seo如何优化
- ssr
- 预渲染:prerender-spa-plugin