面试之vue

    科技2023-10-13  101

    目录

    vue是什么?vuex的作用以及优点vue-routerv-if在vue定义使用后,做的什么?Vue实现数据双向绑定原理vue父子组件生命周期执行顺序v-html指令的xss攻击1:前端过滤 WebSocket之心跳包Vue的响应式属性Vue之中 v-for之 :key的作用Vue之组件通讯方式vue的配置属性中的 computed和methods的区别mixin的配置冲突的时候Vue.use() 的作用路由懒加载的方式作用? 也就是 性能优化,vue首屏加载时间过长怎么解决?路由有哪些对象和钩子cookie之参数关于v-bind绑定的自定义属性vue3.0的了解单页面复应用原理之路由的history和hash的原理vue局部样式的原理vuex的原理vue有什么优点?技术层面上来说vue整个事件的流程vue权限校验v-if 和 v-show的区别vue数据已更新,但是视图不跟新的原因及解决方法?vue生命周期如何使用vue实现一个动态加载的toast组件?express中间件的作用vue的伪静态技术?axios的二次封装 还有 拦截器的使用vue响应式数据的理解vue如何检测数组变化为什么vue采用异步渲染?nextTick 实现原理vue中的computed的特点登录的实现

    vue是什么?

    vue是渐进式框架,你需要多少,然后使用多少vue的两个核心 数据驱动组件系统

    vuex的作用以及优点

    vuex的作用 就是用于数据的共享,组件之间的数据共享 vuex的优点: 代码规范数据共享局部调用全局实现响应式 vuex的缺点: 刷新页面(这里的刷新页面指的是 --> F5刷新,属于清除内存了)时vuex存储的值会丢失 因为store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值初始化解决方式:将state的数据保存在localstorage

    vue-router

    路由:用于设置对应的路径,然后将路由和对应的组件联系起来

    v-if在vue定义使用后,做的什么?

    v-if这个指令就是用于判断条件渲染的代码块 里面有一套diff算法逻辑,虚拟dom按照条件来渲染对应的代码块,这也涉及到局部编译问题

    Vue实现数据双向绑定原理

    原理:采用的是数据的劫持 + 订阅者和发布者模式

    数据的劫持

    就是使用 Object.defineProperty(),在数据初始化时,把js对象作为vue实例对象,Object.defineProperty()劫持后,转化为getter/setter属性,

    订阅者和发布者模式

    vue的数据双向绑定,将mvvm数据的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue是用来解析{{}}), 最终利用Watcher搭建Observer和Compile的通讯桥梁,达到数据的变化- view的更新;视图的更新(input) - 数据的更新

    vue父子组件生命周期执行顺序

    加载渲染阶段

    父 beforeCreate – 父 created – 父 beforeMount子 beforeCreate – 子 created – 子 beforeMount – 子 mounted父 mounted

    子组件更新阶段

    父 beforeUpdate子 beforeUpdate – updated父 updated

    父组件更新阶段

    父 beforeUpdate – 父 updated

    销毁阶段

    父 beforeDestroy子 beforeDestroy – destroyed父 destroyed

    v-html指令的xss攻击

    xss:用户写的是一些恶意的 js 脚本这是很危险 或者style

    跨站脚本攻击XSS(Cross Site Scripting)重灾区:评论区,留言区、个人信息、订单信息等

    解决方式:

    00:只渲染信任的内容01:使用 标签替换掉 标签。 利用的就是 标签的这个功能:被包围在 元素中的文本通常会保留空格和换行符,并且文本也会呈现为等宽字体。 02:通过 HTML 转义,可以防止 XSS 攻击。[事情当然没有这么简单啦!请继续往下看]。03:使用前后端过滤的方式!

    1:前端过滤

    对用户的数据输入进行过滤处理,src,href,script,a等等!01:js原生 //转义 元素的innerHTML内容即为转义后的字符 function htmlEncode ( str ) { var ele = document.createElement('span'); ele.appendChild( document.createTextNode( str ) ); return ele.innerHTML; } //解析 function htmlDecode ( str ) { var ele = document.createElement('span'); ele.innerHTML = str; return ele.textContent; }

    WebSocket之心跳包

    假如其中某些客户端掉线的话,那么怎么清理这些掉线的用户呢?socket之中有着一个心跳包,这是不断给服务器发送的一个简单的一条数据,显示该用户还在聊天室之中,那么就不会清理掉这个用户新跳包分为两种:01:客户端向服务器发起心跳包=>01较为合适 02:由服务器发起心跳包!

    Vue的响应式属性

    方式1:data实例化前,配置响应式属性

    方式2:Vue.set(vm.score, “chinese”, 100); => 可以设置为响应式属性! 即使是实例化后,还是可以变为响应式属性!

    注意点:就是这个目标对象 不能设置为vm实例对象 ,也不能设置为initDate对象也不能设置给当前的initDate对象的chinese设置为100 也不能 Vue.set(vm, "chinese", 100); 否则都会报错:只能设置为: Vue.set(vm.score, “chinese”, 100);

    Vue之中 v-for之 :key的作用

    key属性,这是一个给标签或者DOM节点添加一个唯一的标志 => key值必须为唯一和稳定的值(索引值不建议!) 目的:就是Vue在渲染的时候,会查找到相关的标签,假如这个标签存在,但是被销毁了,后续更新了相同的标签, Vue渲染为了提高效率,会把这个保留下来(就地复用),直接在本来的基础上渲染! 虚拟DOM => (Virtual DOM) 虚拟DOM就是一个结构类似于真实DOM的js对象虚拟DOM提高性能的原因: 1:减少DOM节点的操作 console.time()打印时间,console.endtime()2:在一个特点的时间内,过滤掉无效的dom操作,根据初始的dom的状态和结束的dom状态,两者判断有差异,那么就操作dom(这是依靠diff算法来处理的)

    Vue之组件通讯方式

    父 => 子

    父组件引用子组件的时候 采用自定义属性的方式,向子组件传递数据 子组件,使用props来接受父组件传来的数据,然后用来循环遍历等!props:{ dataList:Array }

    子 => 父

    父组件引用子组件的时候 采用自定义属性的方式,向子组件传递数据 子组件,使用props来接受父组件传来的数据,然后用来循环遍历等!props:{ dataList:Array }然后子组件,定义事件,然后点击|| 其他事件 绑定一个方法 然后出发父组件的方法 @click="add" add(){ this.$emit( addItem, 参数 ) }然后父组件,被触发的事件 addItem对数据的修改 需要在父组件引用子组件的时候,自定义一个事件 接受这个子组件触发的函数 <son-com :dataList="dataList"></son-com> @add-item="addItem" addItem(){ this.count++ }

    兄弟组件通讯

    原理就是 子传递父 然后父传递在另外一个子 实现兄弟组件通讯!

    跨组件通讯:Bus事件总线

    this. r o u t e r . p u s h ( ) = > t h i s . router.push() => this. router.push()=>this.router中的路由的挂载到 编程式导航 结合事件!

    v-model

    Vuex

    state 单一状态数据源mutations 同步函数 修改state的唯一方法 this.$store.commit( "触发的函数"."参数" )actions 异步函数 处理异步的修改 this.$store.dispatch( "触发的函数"."参数" )context.commit( "触发的函数"."参数" ) getter 计算属性

    p a r e n t 和 parent和 parentchildren

    vue的配置属性中的 computed和methods的区别

    computed的话,会把处理后的数据缓存浏览器之中,下一次执行的时候,只要数据不发生变化,那么就从缓存之中拿 在调用的时候 add => 因为是getter存储器属性啊!methods的话 在调用的时候 add()

    mixin的配置冲突的时候

    配置属性冲突的时候 => 优先级,就默认先使用父组件的生命周期函数的话,就不会诶覆盖!

    Vue.use() 的作用

    作用:类似一个管道符,对插件的使用安装 Vue.js 插件。 如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。

    路由懒加载的方式作用? 也就是 性能优化,vue首屏加载时间过长怎么解决?

    什么是路由懒加载:就是当你点击触发,跳转到当前路由的时候,才导入这个组件,加载这个组件,不用一开始就加载全部的组件,造成第一次页面打开时候,卡顿效果!

    路由懒加载方法引入 和 传统的路由引入!

    传统的路由引入 就是每一次进入页面,就加载全部的组件,造成页面的卡顿! import Home from '../views/html/Home.vue' const routes = [{ path: '/', name: 'Home', component: Home }, ] 路由懒加载方式 优点:01:就是打包的文件,一一打包到对应的.js文件之中,; 02:就是使得页面加载速度提高! const routes = [{ path: '/', name: 'Home', component: Home }, { //这是采用路由懒加载的方法导入! path: "/profile", name: "Profile", component: () => import("../views/profile/Profile.vue") }]

    注意点:结合这两者方式,因此为了使得Home组件显示最快,这个Home组件是采用路由传统方式,先加载,而其他的组件,则是采用路由懒加载的方式去引入,这样结合使得页面的加载速度提高了,也使得打包的.js文件大大减少了(不会打包到同一个文件夹!)

    路由有哪些对象和钩子

    路由对象 => router路由规则对象 => $route.path 获取到路由的path对应的钩子函数: beforeEach(to,from,next){} =>beforeEnter(to,from,next){} =>

    https://blog.csdn.net/weixin_47409897/article/details/108331129

    cookie之参数

    以键值对的形式参数 expires => 过期时间path => 路径 => 共享cookie / => 根目录下共享cookie/data => /data目录下共享cookie damain => 域名(同域名下的cookie),以文本的形式存在与硬盘之中!

    关于v-bind绑定的自定义属性

    假如父组件引用子组件的时候,自定义了一个属性 然后在子组件之中,使用props去接受这个a属性,那么这个属性属于子组件的! <input v-model="user" a="10"/>假如子组件没有使用props去接受这个属性,那么这个a属性将会写入根组件之中!

    vue3.0的了解

    使用tepyScript 重构了vueObject.defineProperty() 设置响应式属性 修改为 Proxy方式 Object.defineProperty("修改的对象","对象的属性","修改后的值") Proxy({},{修改的对象!}) 优点:性能的提高! 直接监听对象而非属性直接监听数组的变化拦截方式较多(有13种方式)Proxy返回一个新对象,可以只操作新对象达到目的,而Object.defineProperty只能遍历对象属性直接修改(需要用深拷贝进行修改)Proxy作为新标准将受到浏览器厂商重点持续的性能优化

    单页面复应用原理之路由的history和hash的原理

    history的原理

    利用html5的新特性(history新增的state状态来实现的,里面有着pushState() repalceState() 方法!)

    hash的原理

    利用window下的hashcahnge事件来监听hash改变的值,根据对应的hash值,设置跳转到不同的页面!

    vue局部样式的原理

    给局部组件添加一个 scoped data-v-[‘hash值’]css属性选择器::v-deep 可以修改其他组件的样式! >>>

    vuex的原理

    原理:就是把状态存储在vuex中的state状态数据之中,这样的话通过 store.state.XXX 拿到单一状态数据

    vue有什么优点?技术层面上来说

    渐进式框架,就是你需要多少,就引入多少即可!数据双向绑定响应式属性 -> 响应速度快!数据驱动,减少对dom的操作,提升了了性能! -> 虚拟dom!组件化,模块化轻量级的框架,只关注视图层

    vue整个事件的流程

    解析模板成render函数响应式开始监听首次渲染,页面展示,绑定依赖data数据变化,触发render函数,再次渲染

    vue权限校验

    https://blog.csdn.net/weixin_47409897/article/details/108331129router/index.js 路由配置之中 router.beforeEach(function (to, from, next) { //判断当前路由是否需要登录授权!,才能访问 if (to.matched.some(item => item.meta.requiresAuth)) { //从本地拿到 存储的userInfo信息! let userInfo = localStorage.getItem('userInfo') || {}; try { userInfo = JSON.parse(userInfo) } catch (err) { userInfo = {} } // 判断当前用户信息是否包含token if (userInfo.authorization) { //发起请求 验证token是否过期 $request.get("/jwtverify", { params: { authorization: userInfo.authorization } }) .then(res => { // console.log("我是data啊", res.data.code) if (res.data.code === 1) { next() } else { next({ path: "/login", query: { redirectTo: to.fullPath } }) } }) next(); } else { //若不存在 token 那么就去往 登录页面! next({ path: "/home/loginout", query: { // 跳转到登录页面,并传递 当前点击想要去的 目标页面路径 redirectTo: to.fullPath } }) } } else { next(); } })

    v-if 和 v-show的区别

    v-if:就是根据条件判断是否需要创建元素用于显示页面,还是销毁当前元素v-show:就是一开始加载的时候,已经渲染完毕了,然后考虑的是否显示和隐藏 display:block none

    vue数据已更新,但是视图不跟新的原因及解决方法?

    就是对于这个需要更新的数据 在data初始化的时候,设置为响应式数据 https://blog.csdn.net/bigbear00007/article/details/102594645关于对象的添加新的属性 || 删除对象中的属性 Vue.set(对象,对象的属性,对象的属性值) Vue.set(vm.someObject, 'b', 2) 或者 this.$set(this.someObject,'b',2) (这也是全局 Vue.set 方法的别名) Object.assign方法 对象的合并 把后一个参数或多个参数 合并到第一个参数对象身上! object.assign方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象。vm.object = Object.assign( { } , vm.object , {a:’ 1 ‘, b:’ 2 ’ })注意点:object必须是已经声明的对象

    vue生命周期

    vue生命周期就是从vue 实例对象创建 - 使用 - 销毁的阶段,这些阶段都伴随着钩子函数的触发 在初始化数据前,会触发 beforeCreate()钩子函数在注入数据后,会触发created()钩子函数 这是最新拿到data数据的之后对模板的编译,把html解析为dom树,还有css也是解析为样式dom树,两者结合,再加上js渲染引擎渲染,形成一刻虚拟dom树,保存在浏览器内存之中,此时页面是没有挂载上的! 这个阶段后会触发 beforeMount()钩子函数然后根据el挂载视图,若是有template会替换掉el所挂载的,若是有render()也是会替换掉前面的 经过挂载后,会触发mounted()钩子函数,在这里可以操作dom节点,发起ajax请求若是数据data有更新,那么数据更新前会触发 beforeUpdate()钩子函数数据更新后,会触发updated()钩子函数之后,在实例销毁前,会触发beforeDestroy()钩子函数,这时候el还是可以使用的实例销毁后,destroyed() el已经被销毁了,数据的双向绑定已经解绑了! 这里一般用去定时器的取消,ajax的取消! vue一次生命周期会触发几个钩子函数 beforeCreate()created()beforeMount()mounted()

    如何使用vue实现一个动态加载的toast组件?

    https://www.npmjs.com/package/vue-toast-indicator

    express中间件的作用

    中间件:中间件其是一个函数,在响应发送之前对请求进行一些操作 https://blog.csdn.net/weixin_47409897/article/details/107774383 内置中间件 express.static() 静态资源服务器express.json()express.Router() 自定中间件 requestresponsenext() 是否执行下一个中间件

    vue的伪静态技术?

    转载:https://blog.csdn.net/u011280778/article/details/100565982思路: 使用 this.$router.push(location) 来修改 url,完成页面路由跳转使用params来隐式传递url的参数,它类似post,url看不出,使用query来传递参数的话,类似get,url一定会被格式化为http://www.xxx.com/index?id=123,而不能自定义,以html后缀结尾 路由部分 { path: '/share/:detailId', // path用这种写法是这个思路实现伪静态的核心 name: 'detailLink', component: ArticleDetail } 列表页跳转 原理:就是在跳转的时候,给后面拼接 .html checkDetail: async function (articleId, viewCount) { // 阅读量自增 await countPageViews(articleId, Number(viewCount)) // 伪静态路由跳转 this.$router.push({name: 'detailLink', params: {detailId: articleId + '.html'}}) } 详情页面 created: function () { console.log(this.$route) let obj = {} obj.article_id = this.$route.params.detailId.slice(0, -5) // 取文章detail数据 this.$store.commit('setArticles', obj) } 但是有一个坑 详情看原文!

    axios的二次封装 还有 拦截器的使用

    同个页面,多个请求,所有请求完成后,loading才结束,怎么做?(axios拦截器,让每个请求都经过这个拦截器)axios的拦截器?统一的请求头的处理?接口鉴权的方式?怎么校验这个安全?特殊的接口加上请求头,自定义请求头?https://blog.csdn.net/weixin_47409897/article/details/108963806

    vue响应式数据的理解

    数组和对象类型的值变化时如何劫持? 对象内部通过defineReactive方法,使用Object.definedProperty将属性劫持(只劫持已存在的属性,转化为getter & setter 响应式属性)数组则是通过重写数组的方式! 注意点:就是这种方式,性能不好,因为对象上的属性过多,每一次遍历太多,浪费性能! <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="app"></div> <script> let state = { count: 0 } let active; function defineReactive(obj) { //把对象中的每一个属性 转化为响应式属性 for (let key in obj) { let value = obj[key] //保留最初的值 为了get取值 let dep = [] //这个dep 为了实现发布者的效果 Object.defineProperty(obj, key, { get() { if (active) { //只要取值 就收集起来 dep.push(active) //依赖收集 } return value; }, set(newVal) {//触发更新 value = newVal; dep.forEach(watcher => watcher()) } }) } } defineReactive(state) //监听这个属性的变化 const watcher = (fn) => { active = fn; fn() active = null } // 订阅者模式 watcher(() => { app.innerHTML = state.count }) watcher(() => { console.log(state.count); }) </script> </body> </html>

    vue如何检测数组变化

    数组考虑性能原因没有用defineProperty对数组每一项进行拦截,而是选择了重写数组(push,shilf,pop,splice,unshilf sort reverse)方法的重写!

    为什么vue采用异步渲染?

    如果不采用异步更新的话,那么每一次更新数据的时,都会对组件重新渲染一次,为了性能的着想,vue会在本轮数据更新后,再去异步更新视图!

    nextTick 实现原理

    理解:nextTick方法主要是使用了宏任务和微任务,定义了一个异步方法,多次调用nextTick会将nextTick存入队列之中,通过这个异步方法清空当前队列。所以这个nextTick是异步方法!

    vue中的computed的特点

    默认而言这个是计算属性,有着缓存的效果,对数据带有复杂操作的,可以从methos之中提取到computed之中 也就是当依赖属性发生变化的时候,才会更新视图

    登录的实现

    登录的话,就是把密码和用户名等发送到后端,进行验证,查询是否符合这个用户名和密码,后端返回一个标识符(200 || 1 ),并且携带一个token(这是唯一标志),一般来说把token值存储在本地存储之中,有着这个token存在证明在登录状态,最初的时候点击个人中心,若是没有登录的话,不给进入,直接返回到登录页面,若是本地存在token的话 ,就给进入,期间还需要判断token是否过期!
    Processed: 0.013, SQL: 8