面试必备:VUE面试题(含答案)
1、生命周期都有哪些,以及在这些生命周期中都做过哪些事情
beforeCreate创建之前;无法获取响应数据
created创建之后,可以在这加个loading事件和进行数据请求
beforeMount挂载前 ,在这结束loading,还做一些初始数据的获取,实现函数自执行
mounted挂载后 ,在这发起后端请求,拿回数据,配合路由钩子做一些事情
beforeUpdate数据更新之前
updated数据更新完成之后
beforeDestroy销毁之前 ,你确认删除XX吗?或者确认退出吗?
destroyed销毁之后 ,当前组件已被删除,清空相关内容,在这获取不到dom了
2、组件通信
父传子:props、$attrs/$listeners、$children、$root、provide/inject、$refs
子传父:$emit、$parent、
同级传:eventBus、vuex
3、页面通信
url拼接参数:"/a?a1=a1",接收页面:this.$route.query.a1
query传参:{path: 'a', query: {a2:'a2'}},接收页面:this.$route.query.a2
params传参:{name: 'a', params: {a3:'a3'}},接收页面:this.$route.params.a3
动态路由传参:/path/a4 ,接收页面:this.$route.params.id,路由:path: "/a/:id"
4、$set是干什么的
当数据变化但没有更新视图时使用,例如对象新增加的属性,数组新增加的成员
this.$set(obj,"key","value")
5、$nextTick是干什么的
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
例如:在created生命周期中想要操作dom就可以使用
this.$nextTick(()=>{ ... })可以在mounted之前的生命周期中操作dom
6、mixin是干什么的
提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
var mixin = {data: function () {return {message: 'hello',foo: 'abc'}} } new Vue({mixins: [mixin],data: function () {return {message: 'goodbye',bar: 'def'}},created: function () {console.log(this.$data)// => { message: "goodbye", foo: "abc", bar: "def" }} })
7、简单说说MVVM的理解
MVVM 是 Model-View-ViewModel 的缩写。 Model代表数据模型,也可以在 Model中定义数据修改和操作的业务逻辑。 View 代表UI 组件,它负责将数据模型转化成 UI 展现出来。 ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理 解就是一个同步View 和 Model的对象,连接Model和View。 在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也 会立即反应到View 上。 ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起 来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关 注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维 护完全由 MVVM 来统一管理。
8、watch和computed的区别
Watch只能监听data中的数据变化,computed不需要,watch可以进行异步操作, computed不可以,computed不修改原始数据,通过return返回处理的数据,可以包含大 量的逻辑运算
9、v-if和v-show的区别
9.1、v-show 只是简单的控制元素的 display 属性,而 v-if 才是条件渲染(条件为真,元素将会被渲染,条件为假,元素会被销毁);
9.2、v-show 有更高的首次渲染开销,而 v-if 的首次渲染开销要小的多;
9.3、v-if 有更高的切换开销,v-show 切换开销小;
9.4、v-if 有配套的 v-else-if 和 v-else,而 v-show 没有
9.5、v-if 可以搭配 template 使用,而 v-show 不行
10、为什么不能v-for和v-if一起使用
v-for 优先级是比 v-if 高
永远不要把 v-if 和 v-for 同时用在一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断)
如果避免出现这种情况,则在外层嵌套 template (页面渲染不生成dom节点),再这一层进行 v-if 判断,然后再内部进行 v-for 循环
<template v-if="isShow"><p v-for="item in items"> </template>
如果条件出现再循环内部,可通过计算属性 computed 提前过滤掉那些不需要显示的项
computed:{items:function(){return this.list.filter(function(item){return item.isShow})} }
11、key的作用是什么,值写index和id哪个更好
key是为每个vnode指定唯一的id,在同级vnode的Diff过程中,可以根据key快速的进 行对比,来判断是否为相同节点, 利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快,指定key后,可以 保证渲染的准确性(尽可能的复用 DOM 元素。)赋值时应优先使用id。
12、过滤器怎么使用
// 全局使用 Vue.filter('globalFilter', function(){// ... }) // 局部使用 filters: {formatMoney(num) {// ...}, } <p>过滤器{{ money | formatMoney }}</p>
13、vuex五大核心分别是干什么的
state:Vuex中的基本数据,辅助函数mapState
getters:即从store的state中派生出的状态,有点类似计算属性,辅助函数mapGetters
mutations:是更改Vuex中的store中的状态的唯一方法,是同步的,辅助函数mapMutations
actions:Action 提交的是 mutation,而不是直接变更状态。 Action 可以包含任意异步操作。辅助函数mapActions
Modules:Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutations、actions、getters、甚至是嵌套子模块——从上至下进行类似的分割
14、如何调用mutations和actions的方法
调用mutations:$store.commit('mutations中定义的方法') 调用actions:$store.dispatch('actions中定义的方法') actions调用mutations中的方法: fn(context){ context.commit('mutations中定义的方法'); }
15、vue-router常写属性都有什么
router-link常用属性:
to表示目标路由的链接
replace设置replace属性的话,当点击时,会调用roter.replace()而不是router.push(),所以导航后不会留下history记录,也就是不能回退到上一个页面
append设置append属性后,则在当前路径前添加基路径,例如,我们从/a导航到一个相对路径b,如果没有配置append,则路径为/b,如果配了,则为/a/b
tag 有时候想要<router-link>渲染成某种标签,例如<li>。于是我们使用tag prop 类指定何种标签,同样它还是会监听点击,触发导航。
active-class 设置链接激活时使用的css类名。默认值可以通过路由的构造选项linkActiveClass来全局配置, 默认值为 ‘router-link-active‘
exact "是否激活",默认是false 。
vue-router常用属性:
path路由路径
name路由名字
component导入路由组件
redirect路由重定向
mode路由模式
children子路由
meta路由元信息
16、路由守卫都有哪些以及都做过哪些事情,三个参数分别是干什么的
全局守卫:beforeEach(登录拦截)、afterEach
路由独享守卫:beforeEnter(部分路由的登录拦截)
组件内守卫:beforeRouteEnter(权限管理)、beforeRouteUpdate、beforeRouteLeave
路由全局解析守卫:beforeResolve(这里根据单页面name的指向不同,去访问的接口域名也不同)
三个参数:to:去哪,from:从哪来,next:下一步
当从a页面离开进入b页面时触发的生命周期1.beforeRouteLeave:路由组件的组件离开路由前钩子,可取消路由离开。2.beforeEach: 路由全局前置守卫,可用于登录验证、全局路由loading等。3.beforeEnter: 路由独享守卫4.beforeRouteEnter: 路由的组件进入路由前钩子。5.beforeResolve:路由全局解析守卫6.afterEach:路由全局后置钩子7.beforeCreate:组件生命周期,不能访问this。8.created:组件生命周期,可以访问this,不能访问dom。9.beforeMount:组件生命周期10.deactivated: 离开缓存组件a,或者触发a的beforeDestroy和destroyed组件销毁钩子。11.mounted:访问/操作dom。12.activated:进入缓存组件,进入a的嵌套子组件(如果有的话)。13.执行beforeRouteEnter回调函数next。
17、hash和history模式的区别
hash模式就是url后面写#锚点,由于 hash 值变化不会导致浏览器向服务器发出请求,而且 hash 改变会触发 hashchange 事件(hashchange只能改变 # 后面的url片段);更关键的一点是,因为hash发生变化的url都会被浏览器记录下来,从而你会发现浏览器的前进后退都可以用了,所以人们在 html5 的 history 出现前,基本都是使用 hash 来实现前端路由的
history模式:hash 能兼容到IE8, history 只能兼容到 IE10;hash 本来是拿来做页面定位的,如果拿来做路由的话,原来的锚点功能就不能用了。其次,hash 的传参是基于 url 的,如果要传递复杂的数据,会有体积的限制,而 history 模式不仅可以在url里放参数,还可以将数据存放在一个特定的对象中。history api可以分为两大部分:切换(back、forward、go)和修改(pushState,
replaceState)。history模式的问题:就怕刷新,
18、说说常用指令有哪些,如何自定义指令
v-if :如果是真则渲染节点,否则不渲染节点
v-if、v-else 和 v-else-if :类似js的if...else判断语句
v-show :通过display:none;控制元素显示隐藏
v-for :循环,v-for的优先级高于v-if,不推荐一起使用
v-bind :绑定属性,
v-on :绑定事件,
.stop 阻止事件继续传播
.prevent 事件不再重载页面
.capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
.self 只当在 event.target 是当前元素自身时触发处理函数
.once 事件将只会触发一次
.passive 告诉浏览器你不想阻止事件的默认行为
v-model :数据双向绑定
.lazy 默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步。
.number 自动将用户的输入值转化为数值类型
.trim 自动过滤用户输入的首尾空格
v-text 和 v-html :用来更新textContent和输出真正的html结构
v-pre :主要用来跳过这个元素和它的子元素编译过程。
v-cloak :保持在元素上直到关联实例结束时进行编译。
v-once :关联的实例,只会渲染一次。之后的重新渲染,实例极其所有的子节点将被视为静态内容跳过,这可以用于优化更新性能。
// 自定义指令 v-focusdirectives: {focus: {// 指令的定义inserted: function(el) {el.focus();},},},
19、vue插槽如何使用
// 比如新建一个<base-layout> 组件 <div class="container"><header><slot name="header"></slot></header><main><slot></slot></main><footer><slot name="footer"></slot></footer> </div> // 使用插槽 <base-layout><template v-slot:header> // 或者 <template #header><h1>Here might be a page title</h1></template> <template v-slot:default><p>A paragraph for the main content.</p><p>And another one.</p></template> <template v-slot:footer><p>Here's some contact info</p></template> </base-layout> // 作用域插槽,比如新建一个<current-user>组件 <span><slot v-bind:user="user">{{ user.lastName }}</slot> </span> // 使用插槽 <current-user><template v-slot:default="slotProps">{{ slotProps.user.firstName }}</template> </current-user> // 或者缩写 <current-user v-slot="slotProps">{{ slotProps.user.firstName }} </current-user>
20、vue单页应用优缺点
优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组 件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、 快速、模块友好。 只关心数据,不关心DOM。插件众多。维护状态方便。
缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持 SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏 览器的导航按钮需要自行实现前进、后退。
21、为什么做SSR,如何实现
更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
更快的内容到达时间,特别是对于缓慢的网络情况或运行缓慢的设备。通常 可以产生更好的用户体验。
开发条件所限。浏览器特定的代码,只能在某些生命周期钩子函数中使用; 一些外部扩展库可能需要特殊处理,才能在服务器渲染应用程序中运行。
涉及构建设置和部署的更多要求。与可以部署在任何静态文件服务器上的完 全静态单页面应用程序 (SPA) 不同,服务器渲染应用程序,需要处于 Node.js server 运行环境
更多的服务器端负载
通过后端返回html结构,在前端进行渲染展示,可使用Nuxt实现。
22、如何实现路由懒加载
为给客户更好的客户体验,首屏组件加载速度更快一些,解决白屏问题。
可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力
减少首页加载用时。
component: () => import('./Foo.vue') // 或者 component: resolve => require(['@/components/home'],resolve)
23、less如何设置全局样式
// vue.config.js 中 function addStyleResource(rule) {rule.use("style-resource").loader("style-resources-loader").options({patterns: [path.resolve(__dirname, "./src/assets/less/global.less")],}); } // module.export 中 使用lesscss: {loaderOptions: {less: {lessOptions: {javascriptEnabled: true,globalVars: {primary: "#fff",},},},},}, // less全局变量chainWebpack: (config) => {const types = ["vue-modules", "vue", "normal-modules", "normal"];types.forEach((type) =>addStyleResource(config.module.rule("less").oneOf(type)));},
24、scoped的作用是什么
scoped的意思是下面的样式的作用域就是当前这个组件,不会影响全局的样式
25、$router和$route的区别
$router是路由跳转,$route是路由信息
26、data:{}和data(){return {}} 的区别
因为不使用return包裹的数据会在项目的全局可见,会造成变量污染,使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件。起到保护源数据的效果。
27、axios的配置、封装、拦截和跨域
// 跨域:在config文件夹中的index.js中的devServe中填写 proxyTable:{ // cli3.0+ 是在vue.config.js中配置proxy'/api':{Target:’代理服务器的目标地址’,changeOrigin: true,PathRewrite: {“^/api”:” ”}} }
// 封装和拦截import axios from "axios"; const http = axios.create({baseURL: "/api",timeout: 5000,headers: {"Context‐Type": "application/json",},});// 请求拦截http.interceptors.request.use((res) => {// const token = sessionStorage.getItem('token') ? sessionStorag.getItem('token') : '';// if(token){给headers添加token}return res;},(err) => {return err;});// 响应拦截http.interceptors.response.use((res) => {// const code = res.code// if(code === 404){router.replace()}// if(code === 200){router.replace()}return res;},(err) => {return err;}); function get(url, params = {}) {return new Promise((resolve, reject) => {http.get(url, params).then((res) => resolve(res)).catch((err) => reject(err));});} function post(url, params = {}) {return new Promise((resolve, reject) => {http.post(url, params).then((res) => resolve(res)).catch((err) => reject(err));});} export { get, post };
28、cli各版本构建项目的命令和启动命令
创建项目: cli2.0:vue init webpack 项目名 cli3.0+:vue create 项目名 启动项目: cli2.0:npm run dev cli3.0+:npm run serve
29、简单谈谈你对vue3.0的理解
29.1、vue3.0和vue2.0最大的区别就是api从原来的options API 变成了 composition API + options API ,编写代码更灵活、复用率更高。
29.2、vue3.0比vue2.0快2倍,Tree-shaking 更友好
29.3、vue3.0支持TypeScript以及PWA
29.4、数据双向绑定从Object.defineProperty变成了 new Proxy,不用再使用$set了
29.5、其他方面的更改:支持自定义渲染器、支持 Fragment和 Protal组件等。
30、简单说说双向绑定的原理
// 发布订阅模式实现的数据依赖采集器class Dep {constructor() {this.subs = [];}addSub(sub) {this.subs.push(sub);}notify() {this.subs.forEach((sub) => sub.update());}}Dep.depTargets = null; class Watcher {constructor(data, getter) {this.getter = getter;this.value = this.get();}get() {Dep.depTargets = this;let value = this.getter();Dep.depTargets = null;return value;}update() {this.value = this.get();}} const typeTo = (val) => Object.prototype.toString.call(val); // 观察者模式监听所有属性的变化function defineReactive(obj, key, value) {let dep = new Dep();Object.defineProperty(obj, key, {set(newValue) {if (newValue === value) return;value = newValue;dep.notify();}, get() {const topTarget = Dep.depTargets;dep.addSub(topTarget);return value;},});} function walk(obj) {//监听所有属性Object.keys(obj).forEach((key) => {if (typeTo(obj[key]) === "[object Object]") {walk(obj[key]);}defineReactive(obj, key, obj[key]);});} function observe(value) {if (typeTo(value) !== "[object Object]") return null;walk(value);} observe(this.data);new Watcher(this.data, () => {this.$mounte(this.el);});
31、做过哪些vue的性能优化
31.1、长列表性能优化:可以通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。
export default {data: () => ({books: []}),async created() {const books = await axios.get("/api/books");this.books = Object.freeze(books);} };
31.2、优化无限列表性能:如果应用存在非常长或者无限滚动的列表,那么需要采用“窗口化”的技术来优化性能,只需要渲染少部分区域的内容,减少重新渲染组件和创建 dom 节点的时间。window.requestAnimationFrame方法可以设置延迟加载的功能
setTimeout(() => {// 插入十万条数据const total = 100000;// 一次20条,可根据性能问题自己调整const MAX_ONCE = 20;// 渲染数据需要的次数const loopCount = total / MAX_ONCE;let countOfRender = 0;let el = document.querySelector("ul");function add() {// 优化,不允许插入数据引起回流const fragment = document.createDocumentFragment();for (let i = 0; i < MAX_ONCE; i++) {const li = document.createElement("li");li.innerText = `${i} + ${Math.floor(Math.random() * total)}`;fragment.appendChild(li);}el.appendChild(fragment);countOfRender += 1;loop();} function loop() {if (countOfRender < loopCount) {window.requestAnimationFrame(add);}}loop();}, 0);
32、vue的diff算法和虚拟dom
虚拟DOM就是为了解决浏览器性能问题而被设计出来的。若一次操作中有N次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这N次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性添加到DOM树上,再进行后续操作,避免大量无谓的计算量。所以,用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。
vue的diff算法:只进行同层级比较,忽略跨级操作,从两头向中间进行对比。
//diff时调用patch函数,patch接收两个参数vnode,oldVnode,分别代表新旧节点。 function patch (oldVnode, vnode) {if (sameVnode(oldVnode, vnode)) {patchVnode(oldVnode, vnode)} else {const oEl = oldVnode.ellet parentEle = api.parentNode(oEl)createEle(vnode)if (parentEle !== null) {api.insertBefore(parentEle, vnode.el, api.nextSibling(oEl))api.removeChild(parentEle, oldVnode.el)oldVnode = null}}return vnode } // patch函数内第一个if判断sameVnode(oldVnode, vnode)就是判断这两个节点是否为同一类型节点 function sameVnode(oldVnode, vnode){//两节点key值相同,并且sel属性值相同,即认为两节点属同一类型,可进行下一步比较return vnode.key === oldVnode.key && vnode.sel === oldVnode.sel } //也就是说,即便同一个节点元素比如div,他的className不同,Vue就认为是两个不同类型的节点,执行删除旧节点、插入新节点操作。这与react diff实现是不同的,react对于同一个节点元素认为是同一类型节点,只更新其节点上的属性。 //对于同类型节点调用patchVnode(oldVnode, vnode)进一步比较 patchVnode (oldVnode, vnode) {const el = vnode.el = oldVnode.el //让vnode.el引用到现在的真实dom,当el修改时,vnode.el会同步变化。let i, oldCh = oldVnode.children, ch = vnode.childrenif (oldVnode === vnode) return //新旧节点引用一致,认为没有变化//文本节点的比较if (oldVnode.text !== null && vnode.text !== null && oldVnode.text !== vnode.text) {api.setTextContent(el, vnode.text)}else {updateEle(el, vnode, oldVnode)//对于拥有子节点(两者的子节点不同)的两个节点,调用updateChildrenif (oldCh && ch && oldCh !== ch) {updateChildren(el, oldCh, ch)}else if (ch){ //只有新节点有子节点,添加新的子节点createEle(vnode) //create el's children dom}else if (oldCh){ //只有旧节点内存在子节点,执行删除子节点操作api.removeChildren(el)}} } // 更新vnode:updateChildren function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {var oldStartIdx = 0;var newStartIdx = 0;var oldEndIdx = oldCh.length - 1;var oldStartVnode = oldCh[0];var oldEndVnode = oldCh[oldEndIdx];var newEndIdx = newCh.length - 1;var newStartVnode = newCh[0];var newEndVnode = newCh[newEndIdx];var oldKeyToIdx, idxInOld, vnodeToMove, refElm; // removeOnly is a special flag used only by <transition-group>// to ensure removed elements stay in correct relative positions// during leaving transitionsvar canMove = !removeOnly; {checkDuplicateKeys(newCh);}// 如果索引正常while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {// 当前的开始旧节点没有定义,进入下一个节点if (isUndef(oldStartVnode)) {oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left// 当前的结束旧节点没有定义,进入上一个节点} else if (isUndef(oldEndVnode)) {oldEndVnode = oldCh[--oldEndIdx];// 如果旧的开始节点与新的开始节点相同,则开始更新该节点,然后进入下一个节点} else if (sameVnode(oldStartVnode, newStartVnode)) {// 更新节点patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);oldStartVnode = oldCh[++oldStartIdx];newStartVnode = newCh[++newStartIdx];// 如果旧的结束节点与新的结束节点相同,则开始更新该节点,然后进入下一个节点} else if (sameVnode(oldEndVnode, newEndVnode)) {patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);oldEndVnode = oldCh[--oldEndIdx];newEndVnode = newCh[--newEndIdx];// 如果旧的开始节点与新的结束节点相同,更新节点后把旧的开始节点移置节点末尾} else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved rightpatchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm));oldStartVnode = oldCh[++oldStartIdx];newEndVnode = newCh[--newEndIdx];// 如果旧的结束节点与新的开始节点相同,更新节点后把旧的结束节点移置节点开头} else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved leftpatchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);oldEndVnode = oldCh[--oldEndIdx];newStartVnode = newCh[++newStartIdx];} else {// 如果旧的节点没有定义key,则创建keyif (isUndef(oldKeyToIdx)) { oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); }idxInOld = isDef(newStartVnode.key)? oldKeyToIdx[newStartVnode.key]: findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx);// 如果没有定义index,则创建新的新的节点元素if (isUndef(idxInOld)) { // New elementcreateElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm);} else {vnodeToMove = oldCh[idxInOld];if (sameVnode(vnodeToMove, newStartVnode)) {patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue);oldCh[idxInOld] = undefined;canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm);} else {// same key but different element. treat as new elementcreateElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm);}}newStartVnode = newCh[++newStartIdx];}}// 如果旧节点的开始index大于结束index,则创建新的节点 如果新的开始节点index大于新的结束节点则删除旧的节点if (oldStartIdx > oldEndIdx) {refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);} else if (newStartIdx > newEndIdx) {removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);}}
33、vuex页面刷新后数据丢失?和history模式刷新404问题?
// 在页面加载时读取sessionStorage里的状态信息 if ( sessionStorage.getItem('state') ) {this.$store.replaceState( Object.assign( {}, this.$store.state,JSON.parse(sessionStorage.getItem('state') ) ) ) } // 页面刷新时将state数据存储到sessionStorage中 window.addEventListener('beforeunload',()=>{sessionStorage.setItem('state',JSON.stringify(this.$store.state) ) }) // history模式刷新404问题 在vue.config.js中配置 module.exports = {publicPath: '/', //这个必须,引入静态资源需要从根路径引入,否则会找不到静态资源devServer: {// history模式下的url会请求到服务器端,但是服务器端并没有这一个资源文件,就会返回404,所以需要配置这一项historyApiFallback: {index: '/index.html' //与output的publicPath},}, }
34、Vue 开发中如何使用全局状态常量?你都用这个状态常量做什么事情
比如最常见的全局状态常量就是process.env.NODE_ENV
它的值可能是:production、development
就是webpack.config.js中的mode。
{mode: "",entry: "",output: {}} // 比如现在是开发模式,我就显示一个某某功能按钮。 <button v‐if="process.env.NODE_ENV === 'develpment'"> 测试按钮 </button> npm run serve 的时候看的见这个按钮 npm run build 的时候看不见这个按钮
35、动态路由
通过addRoutes() 动态添加路由信息
面试必备:VUE面试题(含答案)相关推荐
- 【撷英采华】阿里面试Linux基础笔试题-含答案
文章目录 一. 阿里面试流程 二. 阿里原题限时答题 三. 参考答案: 四. 总结 一. 阿里面试流程 阿里的面试一般分为笔试和电话面试. 很多大的外包公司都在帮阿里招聘,所以他们的候选人很多. 所以 ...
- java 字符串乱码_这份Java面试题含答案解析竟然真的让你不用在面试上“如履薄冰”...
面试题集共分为以下十部分: 一.Core Java: 1 - 95 题1 - 24 页 基础及语法: 1 - 61 题1 - 13 页 异常: 62 - 69 题13 - 15 页 集合: 70 - ...
- dom不刷新 vue 加数据后_高频出现的Vue 面试题及答案
前言 本文讲解高频出现的 Vue 面试题及答案. 复习前端面试的知识,是为了巩固前端的基础知识,最重要的还是平时的积累! 注意:文章的题与题之间用下划线分隔开,答案仅供参考. Vue 对 MVC.MV ...
- 苏州大学9月计算机考试试题,2016年9月计算机一级考试试题含答案
2016年9月计算机一级考试试题含答案 一.填空题 1.计算机的主机是由____和____组成. 解答:计算机的硬件系统由中央处理器.存储器.输入设备和输出设备等部分组成.中央处理器和内存储器合起来称 ...
- 北大青鸟Java内侧答案_北大青鸟推荐:Java精选笔试题(含答案解析)
北大青鸟推荐:Java精选笔试题(含答案解析)如果你是计算机专业出生,但是还没有找到工作的话,你就得补补技术了,一些关于面试.笔试的题要多刷一刷.有可能你知道答案,但是由于语言组织能力有所欠缺,所以面 ...
- 2017计算机软件考试试题,2017年计算机应用考试试题含答案.doc
文档介绍: 2017年计算机应用考试试题含答案.doc2017年计算机应用考试试题含答案 2017年计算机应用考试试题(含答案) 一.单项选择题 1.下列关于软件的叙述中,正确的是 . A.计算机软件 ...
- 微型计算机主存可以分为,计算机基础试题 (含答案)
计算机基础试题 (含答案) 一.填空题(每空1分,共30分) 1.计算计的软件系统通常分成______软件和______软件. 2.字长是计算机______次能处理的______进制位数. 3.1KB ...
- 去腾讯等BAT面试完的Mysql面试55题总结,含答案大赠送!
[BAT面试:mysql 面试55题] 1.一张表里面有ID自增主键,当insert了17条记录之后,删除了第15,16,17条记录,再把mysql重启,再insert一条记录,这条记录的ID是18还 ...
- 搜索用计算机弹奏9277的数字,计算机基础知识参考试题(含答案)
计算机基础知识参考试题(含答案) 计算机基础知识参考试题及答案解析 一.单选题 1.1946年诞生的世界上公认的第一台电子计算机是( ENIA). 2.第一台计算机在研制过程中采用了哪位科学家的两点改 ...
- 计算机二级的公共基础课水平测试,计算机二级公共基础知识复习试题含答案
计算机公共基础课程,是针对高校非计算机专业学生设立的一门必修计算机基础课程.以下是由学习啦小编整理关于计算机二级公共基础知识复习试题含答案的内容,希望大家喜欢! 计算机二级公共基础知识复习试题含答案( ...
最新文章
- Windows常用工具
- Spring3 MVC 注解---注解基本配置及@controller和 @RequestMapping 常用解释
- html5中Canvas、绘制线条模糊、常见绘制工具、绘制基本图形、绘制图片、面向对象的方式绘制图形图片、绘制文本、帧动画绘制
- Height、offsetWidth、ClientHeight 区别
- Mysql访问中间件--Atlas初探
- Windows 8 VHD 概述与使用
- Linux下使用QQ和查看QQ空间
- 资深码农教你写详细设计(附示例模板)
- Drool学习记录(一) 概念、Helloworld
- AC/DC、DC/DC转换器基础指南(二)
- 失控的热潮:为什么说特斯拉的“电池日”名副其实?
- 信息学奥赛一本通 1362:家庭问题(family)
- 1.0 win10下curl的安装
- 计算机算东西,PCDN边缘计算是个啥东西
- 为大地增添一抹绿色植树节公益活动
- 1.python网页设计,点击按键显示对话窗口
- 关于Fragment与ViewPager交互遇到的问题
- Peano自然数公理系统
- 12306实时余票查询接口
- 怎样快速将PPT文件转换成Word