双向数据绑定的底层原理是什么?
双向数据绑定的原理:数据劫持结合 发布-订阅者模式,通过()来劫持各个属性的getter/setter,在属性变动的时候发布消息给订阅者,通知订阅者数据属性发生改变,触发相应的回调,实现组件的更新
- 需要一个数据监听器Observer,其核心是递归遍历所有属性并通过劫持监听所有属性,如果有变动,在set方法中通知订阅者
- 需要一个订阅器Dep,初始化师徒在get方法中添加订阅者Wather到订阅器中Dep,负责收集所有的订阅者。
- 需要一个订阅者Watcher,可以收到属性的变化通知执行相应的更新函数,从而更新视图。
- 需要一个解析器Compile,可以扫描和解析模板指令,并替换模板数据,初始化视图,给模板指令对应的节点绑定相应的更新函数,初始化相应的订阅器
的指令有哪些?
v-on 事件绑定
v-bind 属性绑定
v-html,v-text内容绑定
v-model 表单双向数据绑定
v-for 列表渲染
v-if,v-else,v-else-if,v-show 条件渲染
v-slot 应用插槽
v-once 只渲染元素和组件一次
v-cloak 该指令会保持在元素上直到关联实例结束编译
v-pre 跳过这个元素和它的子元素的编译过程,加快编译速度
3. Vue中计算属性用哪个选项来定义,语法上它有那些特点?
计算属性定义在computed中
- 计算属性定义时像函数,使用时像变量
- 只要计算属性这个函数内部所依赖的数据发生了变化,就会立即重新计算这个计算属性的值
- 计算属性的计算结果,会被缓存起来,方便下次继续使用;如果计算属性方法中,所以来的任何数据,多没有发生过变化,则不会重新对计算属性求值
组件间通信的方式有哪些,请描述一下每种通信方式?
1.父组件向子组件传值,父组件在子组件身上通过自定义属性传值,子组件内部通过props接收值
2.子组件向父组件传值,父组件在子组件身上通过自定义事件绑定事件,子组件内部通过$emit触发事件并传值给子组件
3.兄弟组件间传值,通过一个空的Vue实例作为*事件总线(事件中心),其中一个兄弟组件用它来监听事件($on),另一个组件触发事件并传值($emit)
/inject,外层通过provide传值,内层通过inject接收值
,vuex中存储的数据是所有组件共享的,可以实现任何两个组件间的通信
指令v-if和v-show的区别是什么?
v-show原理是修改元素的CSS属性(display)来决定实现显示还是隐藏,但元素无论如何都会被渲染
v-if原理是通过操纵是否渲染dom元素来进行显示,隐藏的控制
需要注意的是,v-if需要操作dom元素,有更高的切换消耗,v-show只是修改元素的CSS属性有更高的初次渲染消耗,如果需要非常频繁的切换,建议使用v-show较好,如果运行时条件很少改变,则使用v-if较好
中组件性能优化的思路有哪些?
1.组件懒加载,当访问到某个路由时才动态加载该组件
2.列表渲染使用key,将元素的唯一索引作为key,可以更大化理由dom节点,提升列表渲染性能
3.使用函数式组件,渲染开销低,速度快,因为函数式组件只是个函数
4.多使用v-show,少用v-if可以更快的实现渲染和响应,避免渲染停顿
5.使用keep-alive,保持组件的数据缓存,避免被重新渲染
中添加动画效果用哪个组件,入场动画包括那些类,出场动画包括哪些类?
transision组件
入场动画包括:v-enter,v-enter-avtive,v-enter-to
出场动画包括:v-leave,v-leave-active,v-leave-to
通过mode属性的值in-out,out-in控制入场动画和出场动画哪个先执行
- Vue组件在那些清醒下会导致内存泄漏?
- 事件监听,组件卸载时未能及时解绑时间导致内存泄漏
- 未销毁的定时器,组件卸载时未及时销毁定时器会导致内存泄漏
- 未取消的网络请求,组件卸载时未能及时取消网络请求会导致内存泄漏
- v-if指令的条件不成立时,对应组件会立即卸载如果未能及时释放资源会导致内存泄漏
- vue-router跳转到别的组件,当前组件会立即卸载如果未及时释放资源会导致内存泄漏
- Vue中父组件如何调用子组件的方法?
方式一:通过ref获取到子组件的实例,通过子组件实例调用自组件的方法
方式二:通过属性传递函数到子组件,子组件回调该函数将子组件实例以参数形式传递给父组件并保存在父组件中,父组件拿到子组件实例调用子组件的方法
- Vue组件声明周期一共有几个,分别是哪些?
一共是11个
创建期:beforeCreate,created
挂在期:beforeMount,mounted
更新期:beforeUpdate,updated
销毁期:beforeDestory,destoryed
缓存相关函数:activated deactivated
错误捕获函数:errorCaptured
- Vue中跳路由的方式有哪些?
-link,必须将点击的元素包裹在router-link内,router-link最终会渲染成a标签
2.$()会往浏览器历史记录中添加新的历史记录
3.$()会替换浏览器历史记录中的当前历史记录
4.$()切换历史记录,在浏览器已有历史记录中切换
中跳路由传参的方案有哪些?优缺点是什么?
1.动态路由,刷新页面,参数不会丢失,参数显示在地址栏,获取参数this.$
+params,刷新页面,参数会丢失,参数无法看到,获取参数this.$
+query,刷新页面,参数不会丢失,参数以查询字符串形式显示在地址栏 获取参数this.$
13.谈谈对vuex的理解,它有哪些核心概念?
使用vuex可以集中管理应用程序的状态,实现多组件通信
State,负责存储数据
mutations,负责定义同步方法(函数),同步方法可以直接修改state中的数据
actions,负责定义异步方法(函数),异步方法不能直接修改state的数据,异步方法内必须调用一个同步方法,才能修改state中的数据
getters,定义计算方法(类似计算属性),内部的方法不能修改state数据
modules,分模块管理应用程序的状态
plugins,应用其他第三方插件到vuex中
中state的作用是什么?在组件中如何获取state数据?
作用:存储应用程序状态(数据)
获取:$或者使用辅助函数mapState映射state数据到组件的计算属性中
中的mutations的作用是什么?在组建中如何调用mutations中的方法?
作用:定义同步方法(函数),同步方法内可以直接修改state中的数据
调用:$(‘同步方法名’,参数)或者使用辅助函数mapMutations映射同步方法到组件的methods然后调用同步方法
中的actions的作用是什么?在组建中如何调用actions中的方法?
作用:定义异步方法(函数),异步方法不能直接修改state数据,异步方法内部必须调用一个同步方法,才能修改state中的数据
调用:$(‘异步方法名字’,参数)或者使用辅助函数mapActions映射异步方法到组件的methods,然后直接调用异步方法
开启模块化以后,调用模块A的同步方法add的写法是什么?
(‘A/add’)
(‘模块名/方法名’)
中如何根据用户权限动态生成菜单按钮,思路是什么?
- 从后台接口获取用户权限列表roles,并保存到vuex中
- 根据用户的权限列表从完整的路由表中过滤出用户有权限访问的路由表
- 用addRoutes()动态添加路由到公共路由表中,形成用户可访问的最终路由表
- 动态渲染权限菜单(由于不同用户权限不同,最终渲染的权限菜单可能不同)
19.Vue3.0中常用的组合API有哪些?
核心api:reactive,ref,toRef,toRefs,computed,watch,watchEffect,provide/inject
生命周期api:
setup,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnMount,onUnMounted
路由api:useRouter,useRoute
状态管理api:useStore
20.Vue3.0的新特性有哪些?
- 性能提升,打包大小减少41%,内存使用减少54%,初次渲染快55%,更新快133%
- 组合式API(Componsition API)
- 更好的Typescript支持
- 底层响应式原理使用ES6的Proxy
-UI组件库常用组件有哪些?
Container,Menu,Table,Pagination,From,Tabs,Message
和的区别是什么?
- Proxy的意思是代理,可以代理对象上的操作,通过new方式创建对象,第一个参数是被代理的对象,第二个参数是对象操作的描述,实例化后返回一个新的对象,当我们对这个新的对象进行操作时就会调用描述中对应的set,get方法
- 只能监听到单个属性的操作,而Proxy除读写外还可以监听属性的删除,方法的调用等
- vue2中我们想要监听数组的变化,基本要依靠重写数组的方法实现,vue3中Proxy可以直接监听数组的变化
23.请简述vue的单向流
- 数据从父级组件传递给子组件,只能单项绑定,子组件不能直接修改从父级传递过来的数据
- 所有的proxy都使得其父子proxy之间形成了一个单向下行绑定:父级proxy的更新会向下流动到子组件中,但是反过来则不行
- 每次父级组件发生更新时,子组件中所有的proxy都会刷新为最新的值
的单页面应用的优缺点有哪些?
优点:
- 用户体验好,快,内容的改变不需要重新加载整个页面,对服务器压力较小
- 前后端分离,比如vue项目
- 完全的前端组件化,前端开发不再以页面为单位,更多的采用组件化的思想,代码结构和组织方式更加的规范,便于修改和调整
缺点:
- 不支持低版本浏览器
- 首次加载页面的时候需要加载大量的静态资源,这个加载时间相对较长
- 不利于SEO(搜索引擎)的优化,单页页面,数据在前端渲染,就意味着没有SEO
- 页面导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)
,computed,与watch的区别是什么?
methods只有主动调用才会执行,返回值可有可无
computed当依赖的属性值(可以是多个属性)中任何一个发生改变就会触发调用,且存在缓存机制,有返回值
watch只能监听一个属性,监听的值发生改变就会被调用,watch可以在数据变化时做一些异步处理或者开销大的操作,没有返回值
26.请描述一下Vuex的数据流?
- 在vue组件里面,通过this.$触发action异步方法执行异步代码获取数据
- 在action异步方法中,通过触发mutation同步方法
- 在mutation同步方法内修改state里面的数据
- 最后由store触发每一个使用state的组件进行更新
27.$router与$route的区别是什么?
$router是vue-router的实例对象,是一个全局路由管理对象,在任何组件中都可以通过$router跳路由
$route是一个路由对象,每一个组件都有一个$route对象,是一个局部路由对象,可以获取当前路由的name,path,params,query等路由参数
与MVC的区别是什么?
MVVM分为三部分:分别是M(Model,模型层),V(View,视图层),VM(ViewModel,V与M连接的桥梁,也可以看作为控制器MVC的C层)V:视图层,负责视图相关,细分下来就是html+css层
M:模型层,主要负责业务数据相关
VM:V与M 沟通的桥梁,负责监听M或者V的修改,是实现MWVM双向绑定的要点;因此开发者只需关注业务逻辑,不需要手动操作 DOM,不需要关注数据状态的同步问题,复杂的数据状态维护完全由MVVM来统一管理。
MVC封装与业务无关的重复代码,形成框架,是模型(model)-视图(view)-控制器(controller)的缩写。模型(Model)数据的储存和处理,再传递给视图层相应或者展示
视图(View)前端的数据展示
控制器(Controller)对数据的接收和触发事件的接收和传递
MVC思想:一种将数据层与视图层进行分离的设计思想
MVVM思想:重要特性:双向绑定,核心思想:数据驱动视图更新.
组件中的data为什么是函数?
组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据
而单纯的写成对象形式,就使得所有组件实例共用了一份data,改变一个组件实例的data就会造成其他组件实例的data也一起改变
30.说一说你理解的Vue路由懒加载(按需加载路由)?
懒加载简单来说就是延迟加载或按需加载,即在需要的时候进行加载,为给客户更好的客户体验,首屏组件加载速度更快,可以解决白屏问题,当构建的项目比较大的时候,懒加载可以分为代码块,提高页面的初始加载效率
使用ES6中的import(推荐)实现路由懒加载:const HelloWorld =() =>import(‘需要加载的模块地址’)
31.为什么有时修改了data中的数据,但是视图没有更新?
如果在实例创建之后添加新的属性到实例上,他不会触发视图更新。
原因:当你把一个普通的JavaScript对象传入Vue实例作为data选项,Vue将遍历此对象所有的属性,当使用劫持这些属性的操作,受JavaScript的限制,Vue不能检测到对象属性的动态添加或删除,由于Vue会在初始化实例对属性执行get set转化过程,所以属性必须在data对象上存在才能Vue转化它,这样才能让它是响应式的
解决方案:可以使用$set()方法,既可以新增属性,又可以触发视图更新
32.什么是?它的应用场景是什么?
数据变化之后无法获取最新的DOM,因为Vue中的DOM更新是异步的,为了在数据变化之后等待Vuewanchegn更新DOM可以在数据变化之后立即使用
(callback)这样回调函数在下次DOM更新循环结束后就会调用,在回调函数中可以直接获取更新后的DOM。
比如:在created()钩子函数进行DOM操作一定要放到()的回调函数中。
created()钩子函数执行的时候,DOM其实并未进行任何渲染,所以此处一定要将DOM操作的js代码放进()的回调函数中
总结:在数据变化后要执行的某个操作,而这个操作需要使用最新的DOM结构的时候,这个操作都应该放进()的回调函数中