42、⾃定义指令(v-check、v-focus)的⽅法有哪些?它有哪些钩⼦函数?还有哪些钩⼦函数参数?
全局定义指令:在 vue 对象的 directive ⽅法⾥⾯有两个参数,⼀个是指令名称,另外⼀个是函数。组件内定义指令:directives钩⼦函数:bind(绑定事件触发)、inserted(节点插⼊的时候触发)、update(组件内相关更新)钩⼦函数参数:el、binding43、vue 的两个核⼼点
数据驱动,组件系统
数据驱动:ViewModel,保证数据和视图的⼀致性组件系统:应⽤类 UI 可以看做全部是由组件树构成的44、delete 和 Vue.delete 删除数组的区别
delete 只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。Vue.delete 直接删除了数组 改变了数组的键值45、Vue-router 跳转和 location.href 有什么区别
使⽤ location.href=/url 来跳转,简单⽅便,但是刷新了页⾯;使⽤ history.pushState(/url), ⽆刷新页⾯,静态跳转;引进 router,然后使⽤ router.push(/url) 来跳转,使⽤了 diff 算法,实现了按需加载,减少了 dom 的消耗。其实使⽤ router 跳转和使⽤ history.pushState() 没什么差别,因为 vue-router 就是⽤了 history.pushState(), 尤其是在 history 模式下。
46、RouterLink 在 IE 和 Firefox 中不起作⽤(路由不跳转)的问题
⽅法⼀
只⽤ a 标签,不使⽤ button 标签
⽅法⼆
使⽤ button 标签和 Router.navigate ⽅法
47、请说下封装 vue 组件的过程?
⾸先,组件可以提升整个项⽬的开发效率。能够把页⾯抽象成多个相对独⽴的模块,解决了我们传统项⽬开发:效率低、难维护、复⽤性等问题。
然后,使⽤ Vue.extend ⽅法创建⼀个组件,然后使⽤ Vue.component ⽅法注册组件。⼦组件需要数据,可以在 props 中接受定义。⽽⼦组件修改好数据后,想把数据传递给⽗组件。可以采⽤ emit ⽅法。
48、params 和 query 的区别
⽤法:query 要⽤ path 来引⼊,params 要⽤ name 来引⼊,接收参数都是类似的,分别是 this.
r
o
u
t
e
r
.
q
u
e
r
y
.
n
a
m
e
和
t
h
i
s
.
router.query.name 和 this.
router.query.name和this.router.params.name。url 地址显⽰:query 更加类似于我们 ajax 中 get 传参,params 则类似于 post,说的再简单⼀点,前者在浏览器地址栏中显⽰参数,后者则不显⽰
注意点:query 刷新不会丢失 query ⾥⾯的数据 params 刷新会丢失 params ⾥⾯的数据
49、vue mock 数据
在项⽬中尝试了 mockjs,mock 数据,实现前后端分离开发。关于 mockjs,官⽹描述的是
前后端分离 不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据。 数据类型丰富 通过随机数据,模拟各种场景。总结:在后端接⼝没有开发完成之前,前端可以⽤已有的接⼝⽂档,在真实的请求上拦截 ajax,并根据 mockjs 的 mock 数据的规则,模拟真实接⼝返回的数据,并将随机的模拟数据返回参与相应的数据交互处理,这样真正实现了前后台的分离开发。
与以往的⾃⼰模拟的假数据不同,mockjs 可以带给我们的是:在后台接⼝未开发完成之前模拟数据,并返回,完成前台的交互;在后台数据完成之后,你所做的只是去掉 mockjs:停⽌拦截真实的 ajax,仅此⽽已。
50、vue 初始化页⾯闪动问题
使⽤ vue 开发时,在 vue 初始化之前,由于 div 是不会 vue 管的,所以我们写的代码在还没有解析的情况下会容易出现花屏现象,看到类似于 {{message}} 的字样,虽然⼀般情况下这个时间很短暂,但是我们还是有必要解决这个问题的。
⾸先:在 css ⾥加上 [v-cloak]{display:none;},如果没有彻底解决问题,则在根元素加上 style=“display:none;” :style=“{display:block}”
51、vue 更新数组时触发视图更新的⽅法
push();pop();shift();unshift();splice();sort();reverse()
52、vue 常⽤的 UI 组件库
Mint UI,element,VUX
53、mint-ui 是什么?怎么使⽤?说出⾄少三个组件使⽤⽅法?
基于 vue 的前端组件库。npm 安装,然后 import 样式和 js,vue.use(mintUi)全局引⼊。在单个组件局部引⼊:import {Toast} from ‘mint-ui’。
组件⼀:Toast(‘登录成功’);组件⼆:mint-header;组件三:mint-swiper54、Vue ⾥⾯ router-link 在电脑上有⽤,在安卓上没反应怎么解决?
Vue 路由在 Android 机上有问题,babel 问题,安装 babel polypill 插件解决
55、Vue2 中注册在 router-link 上事件⽆效解决⽅法
使⽤ @click.native。原因:router-link 会阻⽌ click 事件,.native 指直接监听⼀个原⽣事件。
56、简述 MVVM 框架
Model: 代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑。
View: 代表 UI 组件,它负责将数据模型转化成 UI 展现出来。
ViewModel: 监听数据模型的改变和控制视图行为、处理用户交互,简单理解就是一个同步 View 和 Model 的对象,连接 Model 和 View。
57、vue2 和 vue3 区别
写法上的区别: vue2 使用的是options(选项)Api
,vue3 的是composition Api
(当然 vue3 也兼容composition api
)。options Api
中methods,compute,data
等 api 都是分散的。而composition api
中的代码是根据逻辑功能来组织的, 我们可以将一个功能所定义的methods,compute,data
等 api 会放在一起, 让我们可以更灵活地组合组件逻辑。vue2 将响应式数据放到 data 函数中, 而 vue3 则是使用ref
和reactive
将数据声明为响应式响应式实现方式: vue2 中是通过Object.defineProperty
对数据劫持实现的, vue3 中则是使用Proxy
对数据代理实现的。生命周期区别: vue3 中将beforeCreate
和created
合并到了setup
函数中根节点: vue3 组件允许多个根节点, 而 vue2 只允许一个内置组件: vue3 新增了传送组件Teleport
和异步依赖处理组件Suspense
58、v-if 和 v-show
v-if
表示一个 dom 元素是否被创建,而v-show
则是控制这个 dom 元素的display
属性是否为none
一般在频繁切换状态的地方使用v-show
,v-if
则更适合条件不经常改变的场景,因为它切换开销相对较大 59、v-for 和 v-if 优先级
开发过程中一般不建议同时将 v-for 和 v-if 放在一个标签中使用Vue2 中 v-for 的优先级会更高,所以会先执行循环,再进行 v-if 判断,所以这样就会导致无论需不需展示这个元素,都会先遍历整个列表在 Vue3 中 v-if 的优先级会更高,但是当我们遍历一个数组的时候,根据数组中的某个元素进行 v-if 判断的时候就会报错,因为 v-if 会先执行此时还没有拿到这个数组。所以 Vue3 中会报错60、介绍 Vue 插槽用法
插槽slot
可以理解为占坑,当使用一个组件的时候,在组件标签里的对应的内容就会替换掉这个组件中的slot
标签。
插槽分为默认插槽
,具名插槽
,作用域插槽
。
默认插槽子组件中用slot
标签来确定渲染位置,父组件使用它时直接在子组件的标签内写入内容即可
//子组件<template> <slot /></template>//父组件<Child> <div>默认插槽</div></Child>
具名插槽
顾名思义就是具有名字的插槽,子组件中可以用name
熟悉对slot
命名,父组件在使用的时候通过template
中的v-slot:name
或者#name
来定义这个插槽中的内容
//子组件<template> <slot ></slot></template>//父组件<Child> <template v-slot:content>具名插槽内容</template></Child>
作用域插槽
子组件中的slot
可以通过类似组件属性传递的方式将子组件的值传递给父组件中这个子组件的插槽内容中
(子组件标签内),在父组件使用子组件的时候要用v-slot
的值进行接收这些参数,默认插槽可以将其直接写在子组件标签上,具名插槽则写在template
上。而传过来的值只能在子组件标签中或者template
标签中使用。所以在父组件作用域中获取到了子组件作用域中的变量,可以认为作用域插槽延伸了子组件数据的作用范围,因此叫做作用域插槽
61、过滤器的作用,如何实现一个过滤器
过滤器是用来过滤数据的,在 Vue 中使用 filters 来过滤数据,filters 不会修改数据,而是过滤数据,改变用户看到的输出
使用场景:
需要格式化数据的情况,比如需要处理时间、价格等数据格式的输出 / 显示。比如后端返回一个 年月日的日期字符串,前端需要展示为 多少天前 的数据格式,此时就可以用 fliters 过滤器来处理数据。过滤器是一个函数,它会把表达式中的值始终当作函数的第一个参数。过滤器用在插值表达式 {{}} 和 v-bind 表达式 中,然后放在操作符 “ | ” 后面进行指示
<li>商品价格:{{item.price | filterPrice}}</li>filters: { filterPrice (price) { return price ? ('¥' + price) : '--' } }
注意 vue3 已经移除了过滤器
62、常见的事件修饰符及其作用
.stop:等同于 JavaScript 中的 event.stopPropagation() ,防止事件冒泡;.prevent :等同于 JavaScript 中的 event.preventDefault() ,防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播);.capture :将事件改成捕获模式, 由外到内触发.self :只会触发自己范围内的事件,不包含子元素;.once :只会触发一次。63、v-model 如何实现的
v-model 其实是一个语法糖, 比如
<input v-model="message" /> 等同于<input :value="message" @input="message=$event.target.value">
63、Vue2 中给 data 中的对象属性添加一个新的属性时会发生什么?如何解决?
Vue2 中对象添加新属性绑定的视图不会更新, 因为 Vue2 中 Object.defineProperty 劫持不到 data 对象中新增的属性, 可以使用this.$set(this.obj, 'b', 'obj.b')
解决
$set() 方法相当于手动的去把 obj.b 处理成一个响应式的属性,此时视图也会跟着改变了。
64、Vue 插件用法
面试一般会问你如何写一个 vue 插件, 所以没写过 vue 插件的最好去亲自体验一下
回答:
vue
实例会有一个use
函数, 它接受的是一个带有install
函数的对象和一个可选的选项对象, 当我们使用 vue.use(plugin)
或者app.use(plugin)
会调用我们插件的install
属性的函数, 并且将当前组件的实例传进来. 所以在插件中就可以对这个实例进行一些操作来实现我们插件的功能
65、Vue 自定义指令
vue 官方提供了 v-text、v-for、v-model、v-if 等常用的指令。除此之外 vue 还允许开发者自定义指令。面试经常会问什么是自定义指令? 你用自定义指令做过哪些功能?
回答 1: 什么是自定义指令?
自定义指令包含局部指令和全局指令, 在模板中使用指令前必须先使用directives
选项注册。局部指令指在某个组件中注册, 而全局则是将指令注册到全局, 通常在 main.js 中注册。自定义指令由一个包含类似组件生命周期钩子的对象来定义。它的生命周期钩子包含created
,beforeMount
,mounted
,beforeUpdate
,updated
,beforeUnmount
,unmounted
,常用的钩子为mounted
和 updated
, 它接受el
,binding
等参数.binding
参数的值一般包含绑定到这个元素上的信息, 比如下面这个指令 <div v-example:foo.bar="baz">
它的 binding 会是这个对象
{ arg: 'foo', modifiers: { bar: true }, value: /* `baz` 的值 */, oldValue: /* 上一次更新时 `baz` 的值 */ }
回答 2: 你用自定义指令做过哪些功能?
数据埋点, 通过绑定自定义事件传入点击当前元素需要埋点的事件名, 在指令中监听当前元素的点击事件后调用后台接口将事件名传入权限控制, 通过绑定自定义事件传入控制当前元素的权限字段, 在指令中获取到当前元素根据权限字段来控制该元素的状态 (显示, 隐藏等)66、computed 和 watch
computed 是计算属性, 依赖其它属性值, 用于解决模板中放入过多的逻辑会让模板过重且难以维护的问题.watch 是侦听器, 当我们需要根据一个属性的变化而做出一些处理的时候, 可以使用 watch 来对这个属性进行监听computed 具有缓存的特点, 即当它所依赖的属性发生改变的时候它才会重新执行内部逻辑. 如下代码<template> <div>{{ addSum }}</div> <div>{{ addSum }}</div> <div>{{ addSum }}</div></template><script setup>import { computed, ref, watch } from "vue";const a = ref(1)const b = ref(2)let addSum = computed(() => { console.log('内部逻辑执行') return a.value + b.value})</script>
页面多次使用addSum
, 但是只会打印一次 “内部逻辑执行”
immediate:true
首次才会执行监听watch 默认只监听一层数据, 不监听多层数据里属性的变化, 需要设置deep:true
才会进行深度监听 67、vue 生命周期
Vue2(选项式 API) | Vue3(setup) | 描述 |
---|---|---|
beforeCreate | - | 实例创建前 |
created | - | 实例创建后 |
beforeMount | onBeforeMount | DOM 挂载前调用 |
mounted | onMounted | DOM 挂载完成调用 |
beforeUpdate | onBeforeUpdate | 数据更新之前被调用 |
updated | onUpdated | 数据更新之后被调用 |
beforeDestroy | onBeforeUnmount | 组件销毁前调用 |
destroyed | onUnmounted | 组件销毁完成调用 |
68、vue 父子组件生命周期执行顺序
这个相对于上一个问题稍微复杂一点, 可以试着理解记忆或者直接记住吧
渲染过程
#mermaid-svg-czhhfdPqQmB0CYtp {font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-czhhfdPqQmB0CYtp .error-icon{fill:#552222;}#mermaid-svg-czhhfdPqQmB0CYtp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-czhhfdPqQmB0CYtp .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-czhhfdPqQmB0CYtp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-czhhfdPqQmB0CYtp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-czhhfdPqQmB0CYtp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-czhhfdPqQmB0CYtp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-czhhfdPqQmB0CYtp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-czhhfdPqQmB0CYtp .marker.cross{stroke:#333333;}#mermaid-svg-czhhfdPqQmB0CYtp svg{font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-czhhfdPqQmB0CYtp .label{font-family:“trebuchet ms”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-czhhfdPqQmB0CYtp .cluster-label text{fill:#333;}#mermaid-svg-czhhfdPqQmB0CYtp .cluster-label span{color:#333;}#mermaid-svg-czhhfdPqQmB0CYtp .label text,#mermaid-svg-czhhfdPqQmB0CYtp span{fill:#333;color:#333;}#mermaid-svg-czhhfdPqQmB0CYtp .node rect,#mermaid-svg-czhhfdPqQmB0CYtp .node circle,#mermaid-svg-czhhfdPqQmB0CYtp .node ellipse,#mermaid-svg-czhhfdPqQmB0CYtp .node polygon,#mermaid-svg-czhhfdPqQmB0CYtp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-czhhfdPqQmB0CYtp .node .label{text-align:center;}#mermaid-svg-czhhfdPqQmB0CYtp .node.clickable{cursor:pointer;}#mermaid-svg-czhhfdPqQmB0CYtp .arrowheadPath{fill:#333333;}#mermaid-svg-czhhfdPqQmB0CYtp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-czhhfdPqQmB0CYtp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-czhhfdPqQmB0CYtp .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-czhhfdPqQmB0CYtp .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-czhhfdPqQmB0CYtp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-czhhfdPqQmB0CYtp .cluster text{fill:#333;}#mermaid-svg-czhhfdPqQmB0CYtp .cluster span{color:#333;}#mermaid-svg-czhhfdPqQmB0CYtp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-czhhfdPqQmB0CYtp :root{–mermaid-font-family:“trebuchet ms”,verdana,arial,sans-serif;}
父beforeCreate
父created
父beforeMount
子beforeCreate
子created
子beforeMount
子mounted
父mounted
更新过程
#mermaid-svg-dU9lCSZuMx8fiJaw {font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-dU9lCSZuMx8fiJaw .error-icon{fill:#552222;}#mermaid-svg-dU9lCSZuMx8fiJaw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dU9lCSZuMx8fiJaw .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-dU9lCSZuMx8fiJaw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dU9lCSZuMx8fiJaw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dU9lCSZuMx8fiJaw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dU9lCSZuMx8fiJaw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dU9lCSZuMx8fiJaw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dU9lCSZuMx8fiJaw .marker.cross{stroke:#333333;}#mermaid-svg-dU9lCSZuMx8fiJaw svg{font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dU9lCSZuMx8fiJaw .label{font-family:“trebuchet ms”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-dU9lCSZuMx8fiJaw .cluster-label text{fill:#333;}#mermaid-svg-dU9lCSZuMx8fiJaw .cluster-label span{color:#333;}#mermaid-svg-dU9lCSZuMx8fiJaw .label text,#mermaid-svg-dU9lCSZuMx8fiJaw span{fill:#333;color:#333;}#mermaid-svg-dU9lCSZuMx8fiJaw .node rect,#mermaid-svg-dU9lCSZuMx8fiJaw .node circle,#mermaid-svg-dU9lCSZuMx8fiJaw .node ellipse,#mermaid-svg-dU9lCSZuMx8fiJaw .node polygon,#mermaid-svg-dU9lCSZuMx8fiJaw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dU9lCSZuMx8fiJaw .node .label{text-align:center;}#mermaid-svg-dU9lCSZuMx8fiJaw .node.clickable{cursor:pointer;}#mermaid-svg-dU9lCSZuMx8fiJaw .arrowheadPath{fill:#333333;}#mermaid-svg-dU9lCSZuMx8fiJaw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dU9lCSZuMx8fiJaw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dU9lCSZuMx8fiJaw .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-dU9lCSZuMx8fiJaw .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-dU9lCSZuMx8fiJaw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dU9lCSZuMx8fiJaw .cluster text{fill:#333;}#mermaid-svg-dU9lCSZuMx8fiJaw .cluster span{color:#333;}#mermaid-svg-dU9lCSZuMx8fiJaw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dU9lCSZuMx8fiJaw :root{–mermaid-font-family:“trebuchet ms”,verdana,arial,sans-serif;}
父beforeUpdate
子beforeUpdate
子updated
父updated
销毁过程
#mermaid-svg-ZdXs7utVab0XZIpe {font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ZdXs7utVab0XZIpe .error-icon{fill:#552222;}#mermaid-svg-ZdXs7utVab0XZIpe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZdXs7utVab0XZIpe .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-ZdXs7utVab0XZIpe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZdXs7utVab0XZIpe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZdXs7utVab0XZIpe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZdXs7utVab0XZIpe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZdXs7utVab0XZIpe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZdXs7utVab0XZIpe .marker.cross{stroke:#333333;}#mermaid-svg-ZdXs7utVab0XZIpe svg{font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZdXs7utVab0XZIpe .label{font-family:“trebuchet ms”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZdXs7utVab0XZIpe .cluster-label text{fill:#333;}#mermaid-svg-ZdXs7utVab0XZIpe .cluster-label span{color:#333;}#mermaid-svg-ZdXs7utVab0XZIpe .label text,#mermaid-svg-ZdXs7utVab0XZIpe span{fill:#333;color:#333;}#mermaid-svg-ZdXs7utVab0XZIpe .node rect,#mermaid-svg-ZdXs7utVab0XZIpe .node circle,#mermaid-svg-ZdXs7utVab0XZIpe .node ellipse,#mermaid-svg-ZdXs7utVab0XZIpe .node polygon,#mermaid-svg-ZdXs7utVab0XZIpe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZdXs7utVab0XZIpe .node .label{text-align:center;}#mermaid-svg-ZdXs7utVab0XZIpe .node.clickable{cursor:pointer;}#mermaid-svg-ZdXs7utVab0XZIpe .arrowheadPath{fill:#333333;}#mermaid-svg-ZdXs7utVab0XZIpe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZdXs7utVab0XZIpe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZdXs7utVab0XZIpe .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-ZdXs7utVab0XZIpe .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-ZdXs7utVab0XZIpe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZdXs7utVab0XZIpe .cluster text{fill:#333;}#mermaid-svg-ZdXs7utVab0XZIpe .cluster span{color:#333;}#mermaid-svg-ZdXs7utVab0XZIpe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZdXs7utVab0XZIpe :root{–mermaid-font-family:“trebuchet ms”,verdana,arial,sans-serif;}
父beforeDestroy
子beforeDestroy
子destroyed
父destroyed
注意如果子组件是异步组件的话它们的执行顺序会发生改变,会先执行完父组件的生命周期然后再执行子组件的生命周期
69、vue 导航 (路由守卫)
路由守卫分为全局路由守卫,路由独享守卫,组件路由守卫
全局路由守卫beforeEach
, 接收to、from、next
三个参数,每个路由跳转前都会触发,登录验证时用的比较多beforeResolve
,和beforeEach
类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后调用afterEach,在路由跳转完成后调用,接收 to、from 两个参数 路由独享守卫 beforeEnter
, 一般配置在路由配置文件中(router/index.js),对进入某个路由之前进行相关操作
接收to、from、next
三个参数
beforeRouteEnter
, 进入该组件之前调用,无法获取到 vue 实例beforeRouteUpdate
,在当前路由改变,但是该组件被复用时调用beforeRouteLeave
, 在离开当前组件时调用 70、Vue-Router 的懒加载如何实现
使用箭头函数 + import 动态加载
const router = new VueRouter({ routes: [{ path: "/list", component: () => import("@/components/list.vue") }],});
71、路由的 hash 和 history 模式的区别
Vue-Router 有两种模式:hash 模式和 history 模式。默认的路由模式是 hash 模式。
hash 模式简介: hash 模式是开发中默认的模式,它的 URL 带着一个 #,例如:www.abc.com/#/vue,它的 hash 值就是 #/vue。
特点:hash 值会出现在 URL 里面,但是不会出现在 HTTP 请求中,对后端完全没有影响。所以改变 hash 值,不会重新加载页面。这种模式的浏览器支持度很好,低版本的 IE 浏览器也支持这种模式。hash 路由被称为是前端路由,已经成为 SPA(单页面应用)的标配。
原理: hash 模式的主要原理就是 onhashchange() 事件:
window.onhashchange = function (event) { console.log(event.oldURL, event.newURL); let hash = location.hash.slice(1);};
history 模式 简介: history 模式的 URL 中没有 #,它使用的是传统的路由分发模式,即用户在输入一个 URL 时,服务器会接收这个请求,并解析这个 URL,然后做出相应的逻辑处理。 特点: 当使用 history 模式时,URL 就像这样:abc.com/user/id。相比 hash 模式更加好看。但是,history 模式需要后台配置支持。如果后台没有正确配置,访问时会返回 404。 API: history api 可以分为两大部分,切换历史状态和修改历史状态:
修改历史状态:包括了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法,这两个方法应用于浏览器的历史记录栈,提供了对历史记录进行修改的功能。只是当他们进行修改时,虽然修改了 url,但浏览器不会立即向后端发送请求。如果要做到改变 url 但又不刷新页面的效果,就需要前端用上这两个 API。
切换历史状态: 包括 forward()、back()、go() 三个方法,对应浏览器的前进,后退,跳转操作。
总结
对于框架原理只能说个大概,真的深入某一部分具体的代码和实现方式就只能写出一个框架,许多细节注意不到。
算法方面还是很薄弱,好在面试官都很和蔼可亲,擅长发现人的美哈哈哈…(最好多刷一刷,不然影响你的工资和成功率???)
在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。
要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
第一次跳槽十分忐忑不安,和没毕业的时候开始找工作是一样的感受,真的要相信自己,有条不紊的进行。如果有我能帮忙的地方欢迎随时找我,比如简历修改、内推、最起码,可以把烦心事说一说,人嘛都会有苦恼的~
祝大家都有美好的未来,拿下满意的 offer。
加入社区》https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0