VUE简介:
vue是一个构建数据驱动的web界面的渐进式框架。vue.js的目标是通过尽可能简单的API实现响应的数据绑定和组合的视图组件。vue.js借鉴了angular以及react的一些核心思想,总和各自的长处进行了操作以及性能等方面的优化,vue比angular简单,小,运行速度快,都有数据双向绑定,vue与react都使用virtualDOM虚拟DOM,都是提供了组件的视图组件,都有丰富的插件库,react使用jsx渲染页面,vue使用简单的模板。vue也提供了丰富的指令进行操作,同时也有生命周期(常问的面试题)所有的生命周期钩子自动绑定this上下文到实例中,因此可以访问数据,对属性和方法进行运算。vue.js使用了基于HTml的模板语法,允许开发者声明式地讲DOM绑定至底层vue实例的数据。所有的VUE.js模板都是合法的HTml,所以能被遵循规范的浏览器和HTML解析器解析,components进行组件模板加载。他还提供了动画插件,可以结合animate,css进行动画设置。还有自定义指令,过滤器等。然后就是vuex是一个转为vue.js的状态管理模式,vuex解决了组件之间同一状态的共享问题。当我们的应用遇到多个组件共享状态时,会需要多个组件依赖于同一状态,之后使用vuex就可以很好地解决。同时vue可以配合mint-ui这个ui框架快速构建移动端引用
1.如何让css只在当前的组件中起作用?
在组件中的style前面加上scoped。
2.标签的作用。
keep-alive是vue的内置组价,可以是被包含的组件保留状态,或避免重新渲染。它自身不会渲染DOM元素,也不会出现在父组件链中;使用keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁他们。include定义缓存白名单,keep-alive会缓存命中的组件;exclude定义缓存黑名单,被命中的组件将不会被缓存;max定义缓存组件上限,超出上限使用LRU的策略置换缓存数据。(内存管理的一种页面置换算法,对于内存中但又不用的数据快或者内存快叫做LRu,操作系统会根据那些数据属于LRU而将其移除内存而腾出空间来加载另外的数据)
3.vue组件中如何获取dom元素?
使用ref属性获取,在组件模板元素中添加ref属性,在js中使用this.$ref获取。
4.常用的vue指令有哪些和他的用法?
v-model 双向数据绑定(实现表单输入和应用状态之间的双向绑定)
v-for 循环;(基于一个数组或者对象渲染一个列表,vue2.0以上必须配合key使用)
v-if 显示与隐藏(根据表达式的值得真假条件渲染元素,在切换元素及他的数据绑定/组件被销毁并重建)
v-show显示与隐藏(根据表达式值得真假 切换元素的displayCSS属性)
v-bind动态绑定属性(一个或多个动态属性,或一个组件prop到表达式);
v-on事件绑定(用于舰艇指定元素的DOM事件,比如:点击事件或者绑定事件监听器);
v-once 适用于优化更新性能(只渲染元素和组件一次,随后的重现渲染,元素/组件及其所有的子节点将被视为静态内容并跳过,这可以);
5.v-on指令可以同时监听多个函数吗?
可以的,v-on的事件监听类似于DOM原生api添加事件监听addEventListenter。可以用键对值得形式。事件类型:事件名 如果绑定多个相同事件,直接用逗号分割就行。
6.vue循环中为什么要是用key?
每次循环中要是用key给每个节点做唯一标识,保证一个循环中key的值各不相同,以避免vue中的重用机制造成可能的渲染异常,从底层来看,key属性主要为了diff算法就可以正确的识别此节点。并高效的更新细腻DOM。当vue中用v-for更新已渲染过的元素列表时,默认就地复用策略,如果数据项的数据被改变,vue 将不会移动 dom 元素来匹配数据项的顺序,而是简单的复用此处每个元素,并且确保它在特定的索引下显示已被渲染过的每个元素
7.vue组件配置对象中都偶有那些常用字段?分别是什么作用?
data 组建中的数据
props 组件的属性数据,接受父组件的传值
computed 计算属性
components 定义或引用子组件
methods 自定义函数
watch 属性监听
filters 数据过滤器
mounted 生命周期函数
8. 分别简书computed和watch 的使用场景。 (1)watch中的函数不需要调用,computed内部的函数调用时不需要加()
(2)watch的属性是监听,监听属性的变化。computed是计算属性,通过属性计算得来的
(3)computed是当一个属性受多个属性影响时用computed,像购物车结算,watch是当一条数据影响多条数据的时候用watch 像搜索数据
9.vue声明周期函数有哪些?
beforeCreate (组件刚刚实例化,data methods都还没被创建)
create(此时data和methods已经被创建 可以使用 末班还没被编译)
beforeMount (created的下一阶段 模板已经被编译 但还没挂载)
mounted(模板代码已经被加载在网页中 所有事情都已经准备好了 网页开始运行)
beforeUpdate(在网页运行期间data中的数据随时会因为需要更新 在这个阶段数据只是data中更新了但并没与在模板中进行更新所有还是网页显示之前的)
update(数据在data中更新逐渐更新在网页中)
keep-alive相关:
(activated:被keep-alive缓存的组件激活时调用
deactivated:被keep-alive缓存的组件停用时调用)
beforeDestroy(vue实例或者组件在销毁之前执行的函数 ,在这个函数中vue或者组件中所有的属性都是可以使用的)
destroy(vue实例或者组件被销毁后执行的函数 此时所有的东西都会被解绑所有子元素都会被销毁)
10.vue路由的钩子函数有哪些?
全聚德路由钩子函数:beforeEach ,afterEach
单个的路由狗子函数:beforeEnter
组件内的路由钩子函数:beforeRouteEnter ,beforeRouteleave ,beforeRouteUpdate
11.介绍以下vue中组件内的路由守卫(即路由的生命周期/钩子函数),有哪些参数(to,from,next) vue 组件中的路由钩子方法有
beforeRouterEnter (进入路由前调用,这里组件还未创建,不能使用this)
beforeRouterUpdate(路由更新之前被调用,组件不会重新初始化。可以使用this)
beforeRouterleave(离开路由之前被调用,可以访问里面的this属性)
方法里面都有是哪个参数:
to:即将要进入的目标路由对象;
from :当前导航即将要离开的路有对象
next:调用该方法后,才能进入下一个路由钩子函数
12.vue中数据绑定是怎么实现的?双向绑定指令v-model本质是什么?
vue组件data中的数据在组件创建时,都会被改造为set,get类型的属性,当数据发生改变时set方法就会调用,set方法中添加了冲新渲染的代码。
view层输入值影响data的属性值,data的属性值,data属性值改变会更新view的数值变化
v-model相当于 v-bind:value加v-on:input
13.vue中怎么实现非父子组件之间的传值?
在项目规模不是特别大时,可以创建一个空组件作为总线,项目中其他组件都可以通过总线进行传值。
在大型项目中,可以使用vuex进行数据管理,将数据统一房早store中进行管理。 也可以在路由跳转时,通过路传值。
14.vue中路由如何进行传值?
(1)使用url 拼接字符串的形式传值,使用$route.query接收
(2)使用友好URl传值 使用$route.params 接收
(3)使用命名路由params字段传值 使用$route.params接收
(4) 使用query对象传值 使用$route.query接收
15.vue中有哪些数据传递方式?
(1)组件传值:父传子,通过props属性或slot 插槽传递。子传父,通过$emit发射自定义事件传递。非父子,通过bus总路线传递。
(2)路由传值 可通过url 路径传值和编程式导航对象传值
(3)vuex 状态管理传值
16.vuex如何使用?
首先在项目中 npm install vuex 安装
新建vuex状态管理文件,导入vuex 并添加状态数据
在组件中使用mapState()函数映射状态数据并使用
在组件中使用commit()函数提交申请修改状态数据
下载vuex
在src下创建store以及index.js
引入vue和vuex,使用vuex,导出实例对象
在main.js中引入,在.vue文件中使用
17.vuex 的核心概念有哪些?组件如何使用store中的数据如何改变store中的数据?
state=>基本数据 在组件中使用mapState()函数把状态数据映射入组件即可使用
getters=>从基本数据派生的数据 我们在组件中$store.getters获取数据
mutations=>提交更改数据的方法,同步! 我们在组件中使用$store.commit('',params)修改数据
actions=>像一个装饰器,包裹mutations,使之可以异步。使用mapAction()映射入组件使用
modules=>模块化vuex
18.vue中如何处理跨域请求?
vue中处理跨域请求 一般要设置代理服务器实现跨域
在vue 项目的根目录中手动创建 vue.config.js配置文件,在devSever字段中哦诶之服务器代理使用axios请求数据时直接使用代理地址。
19.axios和ajax的区别
axios是通过promise实现对ajax技术的一种封装,就像jquery实现ajax邓庄一样。
简单说:ajax实现了网页的局部数据刷新,axios实现了对ajax的封装。
20.vue和react有那些异同点?
react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单项数据流。react在setState之后会重新走向渲染的流程,入股shouldComponentUpdate返回的是true,就继续渲染。如果返回false就不会重新渲染。
vue的思想是响应式的,基于是数据可变的,通过每一个属性建议wacher来监听,当属性变化的时候响应式的更新对应的虚拟DOM
相同点:
(1)都是通过虚拟DOM实现了视图的渲染与更新
(2)都是组件化编程,把真个项目分割成一个个的组件来实现
(3)都有单项数据流的规则执行数据流动,父组件通过props属性向子组件传值。
不同点:
(1)vue常规用html标签当模板,使用js实现逻辑,视图与逻辑分离。react使用jsx语法实现模板,html和js相结合。
(2)vue组件中的data数据可以直接调用并更新 而react中的state数据需要使用setState()函数执行更新
(3)vue属于渐进式框架,更适用于开发小型灵活的项目,react生态丰富,适用于开大专业,大型的项目。
(4)vue组件中提供了指令,过滤器,属性监听等,可以方便快捷间操作DOM
(5)实现方式:
react的思路是all in js 通过js来生成html所以设计jsx 还有js来操作css
vue 是把html,css js组合到一起。用各自的方式处理,vue有单文件组件可以把三件套写到一个文件中,html提供了模板引擎来处理
(6)代码书写:
react采用面向对象制作组件,api要求很少,书写比较随意
vue采用声明写法,通过大量的固定 options appi 生成页面 例如:methods,data,filter...
(7)外援
react本身提供很少的功能,大多数高阶功能都依赖于社区,如状态管理要用redux
vue本身集成了超多功能,使用方便。例如状态管理的vuex
总之,react的性能优化需要手动去做,而vue的性能优化是自动的。但vue的响应式机制也有问题就是当state特别多的时候,watcher也会很多。到这卡顿。多以大型应用一般用react更加可控
21.vue常用的那些UI组件库。
element(PC)
VUX(移动端)
MIn UI (移动端)
vant(移动端)
22.vue中 v-if和v-show有什么区别
v-if的原理是根据判断条件来动态的进行增删DOM元素,比较耗费性能和内存,频繁显示隐藏不建议使用。只有条件为真时,才能架子啊元素到DOm
v-show 是根据判断条件动态的进行显示和隐藏元素,通过设置样式display为block和none来实现,适用于频繁显示隐藏的情况。不管真假都会加载到DOM
v-if的开销比v-show更大
v-show有更高的初始化渲染消耗
23. vue有那些优缺点
优点:
(1)简单好用:vue.js包含基于HTMl的标准模板,可以更轻松的使用修改现有的应用程序
(2)单页面应用,使用单文件组件结构,用户体验好。
(3)性能比较好,相比其他框架,他占用空间更少,并提供更好的性能。
(4)基于MVVM模式,数据驱动视图,更高效。
(5)适应性强,组件设计可以提高开发的效率,方便代码复用,提升整个项目的可维护性。
缺点:
(1)vue生态环境不如react和angular,但有追赶和超越的趋势
(2)vue不支持IE8
(3)vue封装的比较深入,不利于seo优化,报错不明显
24.什么是MVVM?
MVVM是一种视图和数据逻辑分离的开发模式。他是model-view-viewModel的简写。(model管理数据,view管理视图,viewModel 管理视图和数据的交互)该模式实现了视图和数据逻辑的分离。model模型指的是后端传递的数据,view视图指的是所看到的页面,viewMOdel是链接视图view和模型model的桥梁,从而实现模型model到视图view的转化和视图view到模型model的转化,也就是我们所说的双向数据绑定,使用MVVM模式实现的前端框架有vue和react offsettop 和scrolltop 一般雪碧图都是不会改变的图片。
model:数据管理层(script部分的data属性,专门管理数据)
view:视图层(template)中的代码,负责Ui的构建
viewModel:视图模型层(new Vue({})部分,自动管理数据和视图。重点是双向数据绑定功能,实现了数据变化视图自动变更,视图变化,视图自动联动
25.vue项目怎么打包app?
(1)首先使用webpack打包发布,npm run build
(2)然后通过Hbuilderx新建H5+app项目
(3)第一步打包出dist文件导入项目
(4)在项目中manifest.json文件中进行打包配置
(5)点击hbuilderx工具菜单栏中的原生APP云打包即可
26.vue中虚拟DOM的实现原理
虚拟DOM是通过js对象的结构来记录html标签节点,当前组件数据更细您需要渲染视图时,先用diff算法计算变化前后js对象(也就是虚拟DOM树)结构的不同,得到最小茶叶,然后针对性的更新部分真是DOM节点,这样可以极大提高视图渲染效率,节省内存消耗。
27.请说下封装vue组件的过程。
(1)建立组件的模板,先把架子打起来,写写样式,考虑好组件的基本逻辑
(2)准备好组件的数据输入,即分析好逻辑,定好props里面的数据,类型。
(3)准备好组件的数据输出,即根据组件路基,做好要暴露出来的方法。
(4)调用。
28.mvc是什么?
mvc是model-view-conyroller的缩写。主要目的是对代码的解耦,把混合在一起的代码拆分为3部分。让html中不存在任何代码逻辑,没有js代码痕迹。
以原生HTML为例:
Model:数据模型层
早期前端:弱化的model,不关注model蹭,数据都是从服务器请求下来,直接使用即可。现在前端:使用webstorage,框架中的vuex,redux等管理数据。在TypeScript语言中,新增了数据类型的生命特征,才让model在前端变得尤为重要。
view:视图层
<button id="buton"> button</button>
注意:此按钮没有onclick的事件写法。
controller:控制器层
var button=document.getElementById("button")
button.onclick=function(){alert("点击了button")}
29.vue双向绑定原理
采用数据劫持 结合 发布者定于这模式,通过oject.defineProperty()来劫持个个属性的setter,getter,在数据变动时发布消息给订阅者,触发响应的监听回调。
具体如下:
(一)首先,需要对observe的数据对象进项递归遍历,然后子属性对象的属性,都加上setter getter。这样的话,给这个对象的某个属性赋值,就会触发setter,那么就 监听到数据变化。(其实就是通过objec.defineProperty()实现监听数据变化的)
(二)然后,需要compile解析模板命令,将模板中的变量替换成数据,接着初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者。一点数据有变动,订阅者收到通知就会更新视图
(三)接着,watcher订阅者是Observe和compile之间通信的桥梁,主要负责:1.在自身实例化时,王属性订阅器(dep)里面添加自己2.自身必须有一个update()方法。3.待属性变动,dep.notice()通知时,就调用自身的update()方法,并触发compile中绑定的回调 4.最后,viewmodel(vue实例对象)作为绑定数据的入口,整合observe,compile,watcher三者,通过observe来建ring自己的model数据变化,通过compile来解析编译模板指令,最终利用watacher搭起observe和compile之间的通信桥梁,打到数据变化viewmodel视图更新view;图变化view数据viewmodel变更的双向绑定效果。
30.vuex是什么?
vuex是一个转为vue.js应用程序开发状态管理模式。它采用集中存储管理应用的所有组建的状态,并以响应的柜子保证状态以一种可预测的方式发生变化。
使用场景:
组件间的状态共享:登录状态
组件间的数据共享:购物车的数据,登录token
5个核心属性:
state:数据存放
getters:相当于计算属性
mutation:同步操作,修改数据
action:异步操作
modules;模块化
31.vuex原理?
vuex实现了单项数据流,在全局有一个state存放数据,当租价要更改state中的数据时,必须通过mutation进行,mutation同时提供了定语这模式外部插件调用获取state数据的更新。而当所有异步操作(常见调用后台接口异步获取更新数据)或批量的同步操作需要走Action。但Action也是无法直接修改state的,还是需要通过mutation来修改state的数据。最后根据state的变化,渲染到视图上。
我的理解:
vuex 是 vue 专用的状态管理库。它以全局方式集中管理应用的状态,并且可以 保证状态变更的可预测性。 vuex 主要解决的问题是多组件之间状态共享的问题,利用各种组件通信方式, 我们虽然能够做到状态共享,但是往往需要在多个组件之间保持状态的一致性, 这种模式很容易出现问题,也会使程序逻辑变得复杂。 vuex 通过把组件的共享 状态抽取出来,以全局单例模式管理,这样任何组件都能用一致的方式获取和修 改状态,响应式的数据也能够保证简洁的单向数据流动,我们的代码将变得更结 构化且易维护。 vuex 并非必须的,它帮我们管理共享状态,但却带来更多的概念和框架。如果 我们不打算开发大型单页应用或者我们的应用并没有大量全局的状态需要维护, 完全没有使用 vuex 的必要。一个简单的 Store 模式就足够了。反之, Vuex 将 会成为自然而然的选择。引用 Redux 的作者 Oan Abramov 的话说就是:Flux 架 构就像眼镜:您自会知道什么时候需要它。
我在使用 vuex 过程中有如下理解:首先是对核心概念的理解和运用,将全局状 态放入 state 对象中,它本身一棵状态树,组件中使用 Store 实例的 state 访 问这些状态;然后有配套的 mutation 方法修改这些状态,并且只能用 mutation 修改状态,在组件中调用 commit 方法提交 mutation ;如果应用中有异步操作 或者复杂逻辑组合,我们需要编写 action ,执行结束如果有状态修改仍然需要 提交 mutation ,组件中调用这些 action 使用 dispatch 方法派发。最后是模块 化,通过 modules 选项组织拆分出去的各个子模块,在访问状态时注意添加子 模块的名称,如果子模块有设置 namespace ,那么在提交 mutation 和派发 action 时还需要额外的命名空间前缀。 vuex 在实现单项数据流时需要做到数据的响应式,通过源码的学习发现是借用 了 vue 的数据响应化特性实现的,它会利用 Vue 将 state 作为 data 对其进行 响应化处理,从而使得这些状态发生变化时,能够导致组件重新渲染。
32.vue-router原理?
vue-router通过hash和history两种方式实现前端路由更新视图但不重新请求页面是前段路由原理的核心之一。目前在浏览器环境中这一工鞥主要实现有两种方式:
(1)hash利用URL中的hash.形势上会多个#(http://localhost:8080/#/login)hash(#)的作用是加载URL中只是网页中的位置。#本身及他后面的字符称之为hash,可通过window.loaction.hash获取///hash虽然出现在url中,但不会被包括在http请求中,他是用来知道浏览器动作的,对服务器端完全无用,因此改变hash不会重新加载页面///每一次改变hash,都会在浏览器历史中增加一个记录,利用hash的以上特点,就可以实现前端路由“更新视图但不重新请求页面的”的功能了
(2)history:html5中新增的方法,形式上比hash更好看(http://loaclost:8080/login)History interface 是浏览器历史记录栈提供的接口,通过back()、forward()、go()等方法,我们可以读取浏览器历史记录栈的信息,进行各种跳转操作。从HTML5开始,History interface 提供了2个新的方法:pushState()、replaceState()使得我们可以对浏览器历史记录栈进行修改。这两个方法的共同特点:当前调用他们修改浏览器历史栈后,虽然当前url改变了。但浏览器不会立即发送请求该url,这就为单页面前端路由,更新视图但不重新请求页面提供了基础。(history模式需要后面服务器进行路径重写处理,否则会出现404错误)
33.router-link和$router.push实现跳的原理?
router-link:
m默认会渲染为a标签。可以通过tag属性修改为其他标签
自动为a标签添加click事件,然后执行$router.push()实现跳转
$router.push:
根据路由配置的mode确定使用HTML5History还是hashHistory实现跳转
HTML5History:调用window.history.pushState()跳转
HashHistory:调用HashHistory.push()跳转
34.vue获取数据在那个周期函数?
理论上,应该在created周期中进行网络请求 因为这是最早的methods与data加载完毕的时机。在created发送请求,可以比mounted周期发送请求,提前几毫秒的时机拿到数据。而实际开发中,几毫秒的提前对用户来讲,没有太大的差异,所以created和mounted发送请求都可以。
35.传参
父子传参:
<Son name="zhangcaigou" :age="18"/>
子组件:
<script>
export default{
props:['name','age'],
//或者规定类型写法
props:{name:{type:String},age:{type:Number}}
}
</script>
子父传参:
子组件:
<button v-on:click="$emit('show','Hi,petter')">我是张菜狗</button>
父组件:
<Son @show="satHi"/>
<script>
export defalut{
methods:{
sayHi(msg){
console.log(msg)
}
}
}
</script>
子组件中,点击按钮.$emit(事件名,参数) 触发show事件绑定的方法,传入参数。 show方法中 父组件中定义 @show="sayHi",子的show方法绑定了父的sayHi 子中的参数通过show事件绑定sayHi方法传入父中。
兄弟传参:
兄弟组件间无法直接通信,通信方式有两种:子传父+父传子和事件车
子传父+父传子:此方式效率低,不推荐。依赖共同的的父组件进行信息的转达。
假设A和B两个组件作为兄弟组件,A要向B中传值:
父组件:通过A的事件方式传递 父的函数给A
A组件 :通过$emit()方式 触发父传入的事件,并传入参数
父组件 收到A参数之后,再通过修改传递给B组件 的属性 。实现B的属性修改
总结:
父和A组件,通过子父传参进行信息交互。
父和B组件,通过父子传参进行信息的交互。
事件车:此方法效率较高 推荐使用。
向Vue的原型中,注入一个专门负责坚挺的vue实例
vue.prototype.EventBus=new vue()
A组件中注册引入EventBus.js模块,并向其中注册事件
this.EventBUs.$("change",msg)
B组件中注册changge事件的监听
this.EventBus.$on('change',changeMsg(msg))
methods:{
changeMsg(mag){
//此处就能收到msg,A组件传入的
}
}
vuex 全局数据管理库
父子传参 子组件通过props接受参数
子父传参 $emit方法传递参数
费父子传参,兄弟传参 eventbus (eventbus就是创建一个服务中心,相当于中转站,可以用来传递和接受项目 适合比较小的项目)
36.vue的权限管理
后台管理系统:一般都会有权限模块,用来控制用户能访问那些页面和那些数据接口。
思路:后端返回用户权限,前端根据用户权限处理得到左侧菜单;所有路由在前端定义好,根据后端返回的用户权限筛选出需要挂载的路由,然后使用addRoutes动态挂载路由。
(1)路由定义,分为初始化路由和动态路由。一般来说初始路由只有login,其他路由都挂载home路由之下需要动态挂在。
(2)用户登录,登陆成功之后得到token,保存sessionStorage,跳转到home,此时会进入路由拦截根据token获取用户权限列表
(3)全局路由拦截 ,根据当前用户有没有token和权限列表进行响应的判断和跳转,当没有token时跳转到login,但有token而没有权限列表时候去发请求获取权限等等。
(4)使用vuex管理路由表,根据vuex动态渲染侧边栏组件。
37.vue路由守卫
1.导航被触发
2.在失活的组件里调用beforeRouteleave守卫
3.调用全局的beforeEach守卫
4.在重用的组件里调用beforeRouterUpdate 守卫
5.在路由配置里调用beforeEnter
6.解析异步路由组件
7.在被激活的组件里调用beforeRouteEnter
8.调用全局的beforeResolve守卫
9.导航被确认
10.调用全局的afterEach 钩子
11.触发Dom更新
12.调用beforeRouterEnter守卫中穿个next的回调函数,创建好的组件实例会作为回调函数的参数传入。
全局前置守卫:
const router=newVueRouter({...})
router.beforeEach((to,from,next)=>{
})
全局解析守卫:你可以用router.beforeResolve注册一个全局守卫。这和router.beforEach类似。区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
全局后置钩子:
router.afterEach((to,from)=>{
})
路由独享守卫:
const router =new VueRouter({
router:[
{
path:'/foo',
component:Foo,
beforeEnter:(to,from,next)=>{
}}
]})
组件内的守卫:
beforeRouteEnter(to,from,next){
//在渲染该组件的对应路由被confirm前调用
//不!能!获取组件实例`this`
//因为守卫执行前,组件实例还没被创建
},
beforeRouterUpdate(to,from,next){
//在当前路由改变,但是该组件被复用是时调用。
//举例带有动态的参数路径 /food/:id 在/foo/1和/foo/2之间跳转的时候
//由于会渲染同样的Foo组价,因此组件实例会被复用,而这个钩子就会在这个情况下被调用。
//可以访问组件实例`this`
}
beforeRouteleva(to,from,next){
//导航离开该组件的对应路由时调用
//可以访问组件实例`this`
}
37.解释vue的nextTick
vue更新Dom是异步操作。$nextTick()可以监听DOM更新完毕的时机
当修改了data值,然后马上更新这个dom值,是获取不到的,需要使用nextTick这个回调,让修改后的data渲染更新dom元素以后再获取
<template>
<div>
<h1 id="zhang">{{name}}</h1>
</div>
</template>
<script>
export default{
data(){}{
return{
name:"张菜狗",};
},
mounted(){
this.name="张二狗";
//异步渲染机制,只要mounted方法执行完毕后,name才会更新到DOM
let el=document.getElementById("zhang")
clg(el.innerText);//张菜狗
this.$nextTick(()=>{
//这里是Dom渲染完成之后的回调函数
let el=document.getElementById('zhang')
clg(el.innerText);//张二狗
})
}
}
</script>
38.vue的computed特性
计算属性就是当其依赖属性的值发生变化时,这个属性的值会自动更新,与之相关的DOM部分也会同步自动更新。
使用场景:
在模板中绑定一些数据,这些数据需要经过一些复杂处理之后再展示。但是模板中只能进行简单的逻辑处理,表达式过长或者逻辑复杂 会变得难以阅读及维护此时就把处理数据的逻辑放在计算属性中进行。
<template>
<div>
<h1>总价:{{total}}</h1>
</div>
</template>
<script>
export default{
data(){
return{
goods:[
{name:"滨江区",price:2300,count:1},
{name:'余杭区',price:1400,count:1},
{name:'上城区',price:700,count:2}
]}}
computed:{
total(){
let total=0;
this.goods.forEach((item)=>{
total+=item.price*item.cpunt;
})
return total
}}
}
</scrpit>
39.vue的watch是否可以监听数组
可以监听:数组的元素增删(push,splice)数组元素内部的变化必须手动开启deep:true配置,才可以监听。
export default{
data(){
return{
emps:[
{name:'zhangsan',age:24,skills:['zhangsan','lily']},
{name:'zhangsan',age:24,skills:['zhangsan','lily']},
{name:'zhangsan',age:24,skills:['zhangsan','lily']}
]}}
methods:{
change(){
this.emps[0].name="luoxiang"
this.emps[0].skills.push(111)
}}
watch:{
emps:{
handler:(xx)=>{
clg(xx)}
deep:true//允许监听内容的变化
}}
}
不能监听:数组已有的值得替换
export default{
data(){
return {
emps:[
{name:'zhangsan',age:24,skills:['zhangsan','lily']},
{name:'zhangsan',age:24,skills:['zhangsan','lily']},
{name:'zhangsan',age:24,skills:['zhangsan','lily']}
]}}
methods:{
change(){
//此操作,替换下标0的值,不会被watch监听
this.emps[0]={name:'222',age:333}
}}
watch:{
emps(){
clg(this.emps)}}
}
40.路由跳转怎么传参?
params和query:
1.用法上的(query要用path来引入,params要用name来引入,接受参数都是类似的,分别是this.route.params.name)注意,接受参数时候,已经是router了。
2.展示上的query更加类似于我们的ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数。后者不显示
41.axios理解
是基于promise的http库,可以工作于浏览器,也可以在node.js中使用axios本质是对原生XHR的封装,是promise的实现版本。
特点:
从浏览器创建XHRHttpRequest
从node.js创建http请求
支持promise API
拦截请求和响应
转换请求和相应数据
取消请求
自动转换为JSON数据
客户端支持防止XSRF/CSRF
42.Data为什么是一个函数
是为了在重复创建实例的时候避免共享同一数据,造成数据污染。因为组件是可以复用的,如果data不是一个函数的话,那么大家共享一个data属性值,如果data改变了就会影响其他的组件。
43.为什么v-for和v-if不能一起使用
v-for的优先级比v-if高,如果一起使用的话。每次渲染都要遍历整个列表,如果整个列表的数据有很多,就会造成性能低。页面卡顿的情况,所以要把v-if提到v-for外的一层上。
44.router的区别
route是一个跳转的路由对象
router是vuerouter的一个对象
router 是 VueRouter 的一个对象,通过 Vue.use(VueRouter)和 VueRouter 构造函数得到一个 router 的实例对象,这个对象中是一个全 局的对象,他包含了所有的路由包含了许多关键的对象和属性。
route 是一个跳转的路由对象,每一个路由都会有一个 route 对象,是 一个局部的对象,可以获取对应的 name,path,params,query 等
45.vue的两个核心
数据驱动(视图的内容随着数据的改变而改变)和组件化开发(可以增家代码的复用性,可维护性,可测试性,提高开发效率。方便重复使用,体现了高内聚低耦合)
46.vue常用的修饰符
trim 输入框过滤收尾空格
number 先输入数字就会限制只能输入数字
lazy 输入框改变数据就改变 lazy在逛遍离开input才更新数据
事件修饰符:
stop阻止点击事件冒泡,相当于原生js中的event,stopPropagation()
.prevent防止执行预设的行为 ,相当于原生js中event.preventDefault()
.capture添加事件侦听器时使用事件捕获模式,就是谁有该事件修饰符,就先触发睡谁。
.self只会触法自己范围内的事件,不包括子元素
.once只执行一次
键盘修饰符:
.enter回车键 .tab制表键 .esc返回键 .space空格键 .up向上键 .down向下键 .left向左键 .right想右键
系统修饰符:
.ctrl .alt .shift .meta
47.jQuery和vue的区别
jQuery是选择器选择dom对象,然后对dom对象进行操作赋值,取值事件绑定等。vue是通过vue对象实现数据和视图的双向绑定。vue侧重数据绑定,可以应用于复杂数据操作后台页面,jQuery侧重样式操作,动画效果等,可以应用于一些html5的动画页面。一些需要js操作页面样式的页面
48.单向,双向数据流的区别?
v-bind 单项数据流绑定 插值形式
v-model 双向数据流 用户对view层的更改会直接同步到model层
49.如何扩展组件
mixins,extenda,自定义插槽(slot)
50.介绍一下mixin,一般在什么情况下使用?
less中允许你是用一个类定义样式,然后把他当做变量,在另一个类中只要引用变量名字就能使用他的所有属性,less把这种特性成为mixin。当有多个类,这多个类之间不存在继承关系。但是彼此之间存在可以重复的代码,这个时候就可以考虑使用mixin复用代码
51.vue中的代码优化有那些
懒加载,代码模块化,for循环设置key值,使用keep-alive 防抖节流,图片的懒加载,无状态组件标记为函数组件。
52.请简书vue的单向数据流
父级prop的更新会向下流动到子组件,每次父组件发生变化,子组件所有的prop都会刷新为最新的值。数据从父组件传递给子组件,只能单向绑定,子组件内部不能直接修改父组件传递过来的数据(可以使用data,computed解决)
53.v-text与{{}}与v-html区别
{{}}将数据解析为纯文本,不能显示输出html。
v-html可以渲染输出html
v-text将数据解析为纯文本,不能输出真正的html,与花括号的区别是在页面加载时不显示双花括号
v-text指令:
作用:操作网页元素中的纯文本内容。{{}}是他的另外一种写法
v-text与{{}}区别:
v-text与{{}}等价,{{}}叫末班插值,v-text叫指令。 有一点区别就是,在渲染的数据比较多的时候,可能会把大括号显示出来,俗称“屏幕煽动”
54.vue单页面的优缺点
单页面spa。
优点:前后端分离,用户体验快,内容改变不需要重新加载整个页面。
缺点:不利于seo,初次加载时间消耗长(浏览器一开始就要加载html,css,js所有页面内容都包含在主页面中),页面复杂度提高了,导航不可用。
55.vue中路由跳转的方式(声明式和编程式)
用js方式进行跳转的叫编程式导航 this.$router.push()
用router-link进行跳转的叫声明式,router-view路由出口,路由模板显示到位置
路由中name属性有什么作用?
在router-link中使用name导航到对应路由
使用name导航同时,给子路由传递参数
56.vue的跨域解决方式
1.更改后台的header
2.使用jq提供jsonp
3.用http-proxy-middleware(配置代理服务器)
57.vue路由的实现
前端路由就是更新视图但不请求页面
利用锚点完成切换,页面不会刷新。
官网推荐用vue-router.js来引入路由模块。
定义路由组件。
定义路由,使用component进行路由映射组件,用name导航到对应路由 。 创建router实例,传入routes配置。
创建和挂载根实例。
用router-link设置路由跳转。
58.MVVM与MVC的区别
MVC模型视图控制器,视图时可以直接访问模型,所以,视图里面会包含模型信息。MVc关注的是模型不变,所以mvc中,模型不依赖视图,但是视图依赖模型
MVVm模型视图和vm vm是作为模型和视图的桥梁,当模型层数据改变,vm会检测刀柄通知视图层进行响应的修改
59.vue首屏加载慢的原因,怎么解决,白屏时间怎么检测
原因: 第一次加载页面有很多组件需要渲染 解决办法:
1.路由懒加载 component:()=>import("路由地址")
2.ui框架按需加载
3.gzip压缩
解决白屏问题:
1.使用v-text渲染数据
2.使用{{}}语法渲染数据,但是同时试用v-cloak指令(用来保持在元素上直到关联实例结束时候进行编译)。v-cloak要放在什么位置呢,v-cloak并不需要添加到每个标签,只要在el挂载的标签上添加就可以。
60.vue双绑数据过程中,这边数据改变了怎么通知另一边。
数据劫持和观察者模式
数据劫持:object.defineproperty他的目的是:当给属性赋值的时候,程序可以感知到,就可以控制属性值得有点范围,就可以改变其它的属性的值。
观察者模式,目的是当属性发生改变的时候,使用该数据的地方也可以改变。
61.vuex流程
在 vue 组件里面,通过 dispatch 来触发 actions 提交修改数据的操作, 然后通过 actions 的 commit 触发 mutations 来修改数据,mutations 接收到 commit 的请求,就会自动通过 mutate 来修改 state,最后由 store 触发每一个调用它的组件的更新
62.vuex怎么请求异步数据 1.首先在 state 中创建变量
2.然后在 action 中调用封装好的 axios 请求,异步接收数据,commit 提交给 mutations
Mutations 中改变 state 中的状态,将从 action 中获取到的值赋值给 state
63.vuex中的action如何提交给mutation的
Action 函数接收一个与 store 实例具有相同方法和属性的 context 对象, 可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 获取 state 和 getters
64.vuex的sate特性是?
State 就是数据源的存放地
State 里面的数据是响应式的,state 中的数据改变,对应这个数据的组 件也会发生改变
State 通过 mapstate 把全局的 state 和 getters 映射到当前组件的计算 属性中
65.vuex的Getter特性?
Getter 可以对 state 进行计算操作,它就是 store 的计算属性 Getter 可以在多组件之间复用 如果一个状态只在一个组件内使用,可以不用 getters
66.vuex的mutation特性是?
更改 vuex store 中修改状态的唯一办法就是提交 mutation,可以在回 调函数中修改 store 中的状态
67.vuex的actions特性是?
Action 类似于 mutation,不同的是 action 提交的是 mutation,不是 直接变更状态,可以包含任意异步操作
68.vuex的优势
优点:解决了非父子组件的通信,减少了 ajax 请求次数,有些可以直接 从 state 中获取
缺点:刷新浏览器,vuex 中的 state 会重新变为初始状态,解决办法是 vuex-along,得配合计算属性和 sessionstorage 来实现
69.proxy的理解
vue 的数据劫持有两个缺点:
1、无法监听通过索引修改数组的值的变化
2、无法监听 object 也就是对象的值的变化所以 vue2.x 中才会有 $set 属性的存在
proxy 是 es6 中推出的新 api,可以弥补以上两个缺点,所以 vue3.x 版本用 proxy 替换 object.defineproperty。
70.vue3是如何变得更快的
-
diff 方法优化Vue2.x 中的虚拟 dom 是进行全量的对比。
-
Vue3.0 中新增了静态标记(PatchFlag):在与上次虚拟结点进行对 比的时候,值对比带有 patch flag 的节点,并且可以通过 flag 的信息 得知当前节点要对比的具体内容化。hoistStatic 静态提升 Vue2.x : 无论元素是否参与更新,每次都会重新创建。 Vue3.0 : 对不参与更新的元素,只会被创建一次,之后会在每次渲染时 候被不停的复用。
3.cacheHandlers 事件侦听器缓存 默认情况下 onClick 会被视为动态绑定,所以每次都会去追踪它的 变化但是因为是同一个函数,所以没有追踪变化,直接缓存起来复用 即可。
71.使用 Object.defineProperty() 来进行数据劫持有什么缺点?
在对一些属性进行操作时,使用这种方法无法拦截,比如通过下标方式修改数组数据或者给对象新增属性,这都不能触发组件的重新渲染,因为 Object.defineProperty 不能拦截到这些操作。更精确的来说,对于数组而言,大部分操作都是拦截不到的,只是 Vue 内部通过重写函数的方式解决了这个问题。
在 Vue3.0 中已经不使用这种方式了,而是通过使用 Proxy 对对象进行代理,从而实现数据劫持。使用Proxy 的好处是它可以完美的监听到任何方式的数据改变,唯一的缺点是兼容性的问题,因为 Proxy 是 ES6 的语法。
72. slot是什么?有什么作用?原理是什么?
slot又名插槽,是Vue的内容分发机制,组件内部的模板引擎使用slot元素作为承载分发内容的出口。插槽slot是子组件的一个模板标签元素,而这一个标签元素是否显示,以及怎么显示是由父组件决定的。slot又分三类,默认插槽,具名插槽和作用域插槽。
默认插槽:又名匿名查抄,当slot没有指定name属性值的时候一个默认显示插槽,一个组件内只有有一个匿名插槽。
具名插槽:带有具体名字的插槽,也就是带有name属性的slot,一个组件可以出现多个具名插槽。
作用域插槽:默认插槽、具名插槽的一个变体,可以是匿名插槽,也可以是具名插槽,该插槽的不同点是在子组件渲染作用域插槽时,可以将子组件内部的数据传递给父组件,让父组件根据子组件的传递过来的数据决定如何渲染该插槽。
实现原理:当子组件vm实例化时,获取到父组件传入的slot标签的内容,存放在vm.slot.default,具名插槽为vm.slot中的内容进行替换,此时可以为插槽传递数据,若存在数据,则可称该插槽为作用域插槽。
73.过滤器的作用,如何实现一个过滤器
根据过滤器的名称,过滤器是用来过滤数据的,在Vue中使用filters来过滤数据,filters不会修改数据,而是过滤数据,改变用户看到的输出(计算属性 computed,方法 methods 都是通过修改数据来处理数据格式的输出显示)。
使用场景:
需要格式化数据的情况,比如需要处理时间、价格等数据格式的输出 / 显示。 比如后端返回一个 年月日的日期字符串,前端需要展示为 多少天前 的数据格式,此时就可以用fliters过滤器来处理数据。
过滤器是一个函数,它会把表达式中的值始终当作函数的第一个参数。过滤器用在插值表达式 {{ }} 和 v-bind 表达式中,然后放在操作符“ | ”后面进行指示。
74。Vue data 中某一个属性的值发生改变后,视图会立即同步执行重新渲染吗?
不会立即同步执行重新渲染。Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化, Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。
如果同一个watcher被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环tick中,Vue 刷新队列并执行实际(已去重的)工作。
75. Vue模版编译原理
vue中的模板template无法被浏览器解析并渲染,因为这不属于浏览器的标准,不是正确的HTML语法,所有需要将template转化成一个JavaScript函数,这样浏览器就可以执行这一个函数并渲染出对应的HTML元素,就可以让视图跑起来了,这一个转化的过程,就成为模板编译。模板编译又分三个阶段,解析parse,优化optimize,生成generate,最终生成可执行函数render。
解析阶段:使用大量的正则表达式对template字符串进行解析,将标签、指令、属性等转化为抽象语法树AST。
优化阶段:遍历AST,找到其中的一些静态节点并进行标记,方便在页面重渲染的时候进行diff比较时,直接跳过这一些静态节点,优化runtime的性能。
生成阶段:将最终的AST转化为render函数字符串。
76.对SSR的理解
SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端
SSR的优势:
- 更好的SEO
- 首屏加载速度更快
SSR的缺点:
- 开发条件会受到限制,服务器端渲染只支持beforeCreate和created两个钩子;
- 当需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境;
- 更多的服务端负载。
77.template和jsx的有什么分别?
对于 runtime 来说,只需要保证组件存在 render 函数即可,而有了预编译之后,只需要保证构建过程中生成 render 函数就可以。在 webpack 中,使用vue-loader编译.vue文件,内部依赖的vue-template-compiler模块,在 webpack 构建过程中,将template预编译成 render 函数。与 react 类似,在添加了jsx的语法糖解析器babel-plugin-transform-vue-jsx之后,就可以直接手写render函数。
所以,template和jsx的都是render的一种表现形式,不同的是:JSX相对于template而言,具有更高的灵活性,在复杂的组件中,更具有优势,而 template 虽然显得有些呆滞。但是 template 在代码结构上更符合视图与逻辑分离的习惯,更简单、更直观、更好维护。
78. Vuex和单纯的全局对象有什么区别?
- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
- 不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样可以方便地跟踪每一个状态的变化,从而能够实现一些工具帮助更好地了解我们的应用。
79.为什么 Vuex 的 mutation 中不能做异步操作?
- Vuex中所有的状态更新的唯一途径都是mutation,异步操作通过 Action 来提交 mutation实现,这样可以方便地跟踪每一个状态的变化,从而能够实现一些工具帮助更好地了解我们的应用。
- 每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难
80. Vue3.0有什么更新
(1)监测机制的改变
- 3.0 将带来基于代理 Proxy的 observer 实现,提供全语言覆盖的反应性跟踪。
- 消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制:
(2)只能监测属性,不能监测对象
- 检测属性的添加和删除;
- 检测数组索引和长度的变更;
- 支持 Map、Set、WeakMap 和 WeakSet。
(3)模板
- 作用域插槽,2.x 的机制导致作用域插槽变了,父组件会重新渲染,而 3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能。
- 同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来方便习惯直接使用 api 来生成 vdom 。
(4)对象式的组件声明方式
- vue2.x 中的组件是通过声明的方式传入一系列 option,和 TypeScript 的结合需要通过一些装饰器的方式来做,虽然能实现功能,但是比较麻烦。
- 3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易
(5)其它方面的更改
- 支持自定义渲染器,从而使得 weex 可以通过自定义渲染器的方式来扩展,而不是直接 fork 源码来改的方式。
- 支持 Fragment(多个根节点)和 Protal(在 dom 其他部分渲染组建内容)组件,针对一些特殊的场景做了处理。
- 基于 tree shaking 优化,提供了更多的内置功能。
81.为什么不建议用index作为key?
使用index 作为 key和没写基本上没区别,因为不管数组的顺序怎么颠倒,index 都是 0, 1, 2...这样排列,导致 Vue 会复用错误的旧子节点,做很多额外的工作。
82. DIFF算法的原理
在新老虚拟DOM对比时:
- 首先,对比节点本身,判断是否为同一节点,如果不为相同节点,则删除该节点重新创建节点进行替换
- 如果为相同节点,进行patchVnode,判断如何对该节点的子节点进行处理,先判断一方有子节点一方没有子节点的情况(如果新的children没有子节点,将旧的子节点移除)
- 比较如果都有子节点,则进行updateChildren,判断如何对这些新老节点的子节点进行操作(diff核心)。
- 匹配时,找到相同的子节点,递归比较子节点
在diff中,只对同层的子节点进行比较,放弃跨级的节点比较,使得时间复杂从O(n3)降低值O(n),也就是说,只有当新旧children都为多个子节点时才需要用核心的Diff算法进行同层级比较。
83.虚拟DOM真的比真实DOM性能好吗
- 首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。
- 正如它能保证性能下限,在真实DOM操作的时候进行针对性的优化时,还是更快的。
84. 为什么要用虚拟DOM
(1)保证性能下限,在不进行手动优化的情况下,提供过得去的性能 看一下页面渲染的流程:解析HTML -> 生成DOM -> 生成 CSSOM -> Layout -> Paint -> Compiler 下面对比一下修改DOM时真实DOM操作和Virtual DOM的过程,来看一下它们重排重绘的性能消耗∶
- 真实DOM∶ 生成HTML字符串+重建所有的DOM元素
- 虚拟DOM∶ 生成vNode+ DOMDiff+必要的dom更新
Virtual DOM的更新DOM的准备工作耗费更多的时间,也就是JS层面,相比于更多的DOM操作它的消费是极其便宜的。尤雨溪在社区论坛中说道∶ 框架给你的保证是,你不需要手动优化的情况下,依然可以给你提供过得去的性能。 (2)跨平台 Virtual DOM本质上是JavaScript的对象,它可以很方便的跨平台操作,比如服务端渲染、uniapp等。
85. Composition API与React Hook很像,区别是什么
从React Hook的实现角度看,React Hook是根据useState调用的顺序来确定下一次重渲染时的state是来源于哪个useState,所以出现了以下限制
- 不能在循环、条件、嵌套函数中调用Hook
- 必须确保总是在你的React函数的顶层调用Hook
- useEffect、useMemo等函数必须手动确定依赖关系
而Composition API是基于Vue的响应式系统实现的,与React Hook的相比
- 声明在setup函数内,一次组件实例化只调用一次setup,而React Hook每次重渲染都需要调用Hook,使得React的GC比Vue更有压力,性能也相对于Vue来说也较慢
- Compositon API的调用不需要顾虑调用顺序,也可以在循环、条件、嵌套函数中使用
- 响应式系统自动实现了依赖收集,进而组件的部分的性能优化由Vue内部自己完成,而React Hook需要手动传入依赖,而且必须必须保证依赖的顺序,让useEffect、useMemo等函数正确的捕获依赖变量,否则会由于依赖不正确使得组件性能下降。
虽然Compositon API看起来比React Hook好用,但是其设计思想也是借鉴React Hook的。
86.为什么 Vuex 的 mutation 中不能做异步操作?
- Vuex中所有的状态更新的唯一途径都是mutation,异步操作通过 Action 来提交 mutation实现,这样可以方便地跟踪每一个状态的变化,从而能够实现一些工具帮助更好地了解我们的应用。
- 每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。
87. Vuex 和 localStorage 的区别
(1)最重要的区别
- vuex存储在内存中
- localstorage 则以文件的方式存储在本地,只能存储字符串类型的数据,存储对象需要 JSON的stringify和parse方法进行处理。 读取内存比读取硬盘速度要快
(2)应用场景
- Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。vuex用于组件之间的传值。
- localstorage是本地存储,是将数据存储到浏览器的方法,一般是在跨页面传递数据时使用 。
- Vuex能做到数据的响应式,localstorage不能
(3)永久性
刷新页面时vuex存储的值会丢失,localstorage不会。
注意: 对于不变的数据确实可以用localstorage可以代替vuex,但是当两个组件共用一个数据源(对象或数组)时,如果其中一个组件改变了该数据源,希望另一个组件响应该变化时,localstorage无法做到,原因就是区别。
88.对前端路由的理解
在前端技术早期,一个 url 对应一个页面,如果要从 A 页面切换到 B 页面,那么必然伴随着页面的刷新。这个体验并不好,不过在最初也是无奈之举——用户只有在刷新页面的情况下,才可以重新去请求数据。
后来,改变发生了——Ajax 出现了,它允许人们在不刷新页面的情况下发起请求;与之共生的,还有“不刷新页面即可更新页面内容”这种需求。在这样的背景下,出现了 SPA(单页面应用)。
SPA极大地提升了用户体验,它允许页面在不刷新的情况下更新页面内容,使内容的切换更加流畅。但是在 SPA 诞生之初,人们并没有考虑到“定位”这个问题——在内容切换前后,页面的 URL 都是一样的,这就带来了两个问题:
- SPA 其实并不知道当前的页面“进展到了哪一步”。可能在一个站点下经过了反复的“前进”才终于唤出了某一块内容,但是此时只要刷新一下页面,一切就会被清零,必须重复之前的操作、才可以重新对内容进行定位——SPA 并不会“记住”你的操作。
- 由于有且仅有一个 URL 给页面做映射,这对 SEO 也不够友好,搜索引擎无法收集全面的信息
为了解决这个问题,前端路由出现了。
前端路由可以帮助我们在仅有一个页面的情况下,“记住”用户当前走到了哪一步——为 SPA 中的各个视图匹配一个唯一标识。这意味着用户前进、后退触发的新内容,都会映射到不同的 URL 上去。此时即便他刷新页面,因为当前的 URL 可以标识出他所处的位置,因此内容也不会丢失。
那么如何实现这个目的呢?首先要解决两个问题:
- 当用户刷新页面时,浏览器会默认根据当前 URL 对资源进行重新定位(发送请求)。这个动作对 SPA 是不必要的,因为我们的 SPA 作为单页面,无论如何也只会有一个资源与之对应。此时若走正常的请求-刷新流程,反而会使用户的前进后退操作无法被记录。
- 单页面应用对服务端来说,就是一个URL、一套资源,那么如何做到用“不同的URL”来映射不同的视图内容呢?
从这两个问题来看,服务端已经完全救不了这个场景了。所以要靠咱们前端自力更生,不然怎么叫“前端路由”呢?作为前端,可以提供这样的解决思路:
- 拦截用户的刷新操作,避免服务端盲目响应、返回不符合预期的资源内容。把刷新这个动作完全放到前端逻辑里消化掉。
- 感知 URL 的变化。这里不是说要改造 URL、凭空制造出 N 个 URL 来。而是说 URL 还是那个 URL,只不过我们可以给它做一些微小的处理——这些处理并不会影响 URL 本身的性质,不会影响服务器对它的识别,只有我们前端感知的到。一旦我们感知到了,我们就根据这些变化、用 JS 去给它生成不同的内容。