照抄自网友的前端面试宝典,如有侵权,
- Vue
- 一:Vue的生命周期有哪些,一般在哪一步发起请求及原因?
- 二:keep-alive的使用
- 三:生命周期钩子是如何实现的?
- 四:vue的父组件和子组件生命周期钩子执行顺序
- 五:vue组件间通信有哪些方式?
- 六:vuex
- 七:vue-router中的query与params传参与接参
- 八:vue-router有几种钩子函数,执行流程是怎样的?
- 九:vue-router两种模式的区别?
- 十:spa单页面的理解,优缺点是什么?
- 十一:new Vue() 发生了什么?
- 十二:Vue.use是干什么的?
- 十三:请说一下响应式数据的理解?
- 十四:Vue是如何检测数组变化的?
- 十五:Vue.$set方法是如何实现的?
- 十六:Vue的模板编译原理?
- 十七:`$nextTick()`和 `$forceUpdate()`与`$set`的区别?
- 十八:v-if和v-show的区别?
- 十九:watch、computed和methods的区别?
- 二十:v-model的原理?
- 二十一:watch的属性详解?
- 二十二:vue的插槽?
- 二十三:vue常用命令?
- 二十四:vue的性能优化?
- 二十五:vue-router与location.href的用法区别?
- 二十六:vue的mixin?
- 二十七:vue阻止事件冒泡与js阻止事件冒泡?
- 二十八:vue中的虚拟DOM
- 二十九:vue3.0有什么变化?
- 三十:Vue3.x响应式数据原理?
- 三十一:Proxy与Object.defineProprety优劣对比?
- 小程序
Vue
一:Vue的生命周期有哪些,一般在哪一步发起请求及原因?
一般分为8个阶段:创建前/后,载入前/后,更新前/后,销毁前/后。
另外两个配合keep-alive组件使用:激活前/后。
- 创建前:
beforeCreate
:vue实例挂载元素el和数据对象data都为undefined,还未初始化。在当前阶段data、methods、computed以及watch上的数据和方法都不能被访问。- 创建后:
created
:vue的数据对象data有了,el还没有。可以做一些初始数据的获取。但当前阶段无法与dom进行交互,如果非要,可以通过this.$nextTick()
来异步操作dom。- 载入前:
beforeMount
:vue实例的el和data都已经初始化了,但还是挂载之前为虚拟的dom节点。当前阶段虚拟dom已经创建完成,即将开始渲染。在此时也可以对数据进行更改,不会触发updated。- 载入后:
mounted
:vue实例挂载完成。当前阶段真实don挂载完毕,数据完成双向绑定,可以访问dom节点并操作。- 更新前:
beforeUpdate
:响应式数据更新时调用,发生在虚拟dom打补丁之前,适合在更新之前访问现有的dom,比如手动移除已添加的事件监听器。- 更新后:
updated
:虚拟dom重新渲染和补丁之后调用,新的dom已经更新,避免在这个钩子函数中操作数据,防止死循环
。- 销毁前:
beforeDestroy
:实例销毁前调用,this能获取到实例,常用于销毁定时器,解绑事件。- 销毁后:
destroyed
:实例销毁后调用,所有事件监听器都会被移除,子实例也都会被销毁。- 激活前:
activated
:keep-alive组件激活时调用。- 激活后:
deactivated
:keep-alive组件停用后调用。
第一次进入页面加载的时候,会触发
创建前/后、载入前/后
二:keep-alive的使用
首先简述一下keep-alive的作用,keep-alive可以缓存不活动的组件。
当组件之间进行相互切换的时候,默认会销毁原来的组件,当重新切换回来的时候又重新初始化。
现在有需求切换回来不销毁组件,保持原来的状态,此时用keep-alive就可以实现了。
三:生命周期钩子是如何实现的?
vue的生命周期钩子就是回调函数,创建组件实例的过程中调用对应的钩子方法。核心是一个发布订阅模式,将钩子订阅好,在对应的阶段进行发布。
四:vue的父组件和子组件生命周期钩子执行顺序
父组件挂载一定是等子组件都挂载完成后,才算是父组件挂载完,所以父组件的mounted是在子组件的mounted之后的。
- 渲染:父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
- 刷新:父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated
- 销毁:父beforeDestory -> 子beforeDestory -> 子desstoryed -> 父destoryed
父组件等待子组件完成后,才会执行自己对应完成的钩子。
五:vue组件间通信有哪些方式?
有三种,一种是父子组件传值,一种是兄弟组件传值,一种是隔代组件传值。
props/$emit
适用于父子传值- EventBus公交传值
$emit/$on
$parent/$children
访问父子vuex
数据管理传值localStorage
与sessionStorage
组件传值$attrs/$listeners
隔代组件通信provide/inject
隔代组件通信
六:vuex
vuex是一个专门为vue开发的状态管理模式
- state:储存状态(变量)
- getters:对数据获取之前的再次编译,可以理解为state的计算属性
- mutations:修改状态的方法
- actions:异步操作
- modules:store的子模块,让每一个模块拥有自己的state、mutation、action、getters,使得结构变得非常清晰,方便管理。
七:vue-router中的query与params传参与接参
query:
传参:this.$router.push({path:'/xxx',query:{id:id}})
接参:this.$route.query.id
params:
传参:this.$router.push({name:'xxx',params:{id:id}})
接参:this.$route.params.id
注:
params传参,push里面只能是name:'xxx'
,不能是path。因为params只能通过name来引入路由。
query相当于get请求,页面跳转的时候,地址栏能看见。
params相当于post请求,参数不会在地址栏中显示,传参是$router
,接参是$route
。
八:vue-router有几种钩子函数,执行流程是怎样的?
钩子函数种类有:全局守卫,路由守卫,组件守卫。
- 导航被触发
- 离开的组件调用
beforeRouteLeave
守卫- 调用全局的
beforeEach
守卫- 复用组件里调用
beforeRouterUpdate
守卫- 路由配置里的
beforeEnter
守卫- 解析异步路由组件
- 在被激活的组件里调用
beforeRouteEnter
守卫- 调用全局
beforeResolve
守卫- 导航被确认
- 调用全局
afterEach
钩子dom
更新- 用创建好的实例调用
beforeRouteEnter
守卫传next
的回调函数
九:vue-router两种模式的区别?
vue-router一共有两种路由模式。
hash
、history
。
- hash模式:
hash+hashChange
。
hash
在url中,但不被包括在http
请求中,用来知道浏览器动作,对服务端安全无用。hash
不会重新加载页面,通过监听hash的变化来执行js
代码,从而实现页面的改变。- hash——即地址栏URL中的
#符号
。history
模式:;historyApi+popState
- 只要刷新这个url就会请求服务器,每一次路由改变都会重新加载。
一般场景下,
hash
和history
都可以,除非你更在意颜值,#符号夹杂在URL里看起来确实不太美观
。
如果不想要很丑的hash
,我们可以用路由的history
模式,这种模式充分利用history.pushState Api
来完成,URL跳转而无需重新加载页面。——Vue-router官网。
十:spa单页面的理解,优缺点是什么?
spa(single-page application)仅在web页面初始化时加载相应的HTML、JavaScript和CSS,一旦页面加载完成,spa就不会因为用户的操作而进行页面的重新加载或跳转;而是利用路由机制实现HTML内容的变换,可以避免页面的重新加载。
优点:
- 用户体验好、快。内容改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染。
- spa相对于服务器压力小。
- 前后端分离,架构清晰,前端负责交互逻辑,后端负责数据处理。
缺点:
- 首屏(初次)加载慢:为实现spa页面,需要将加载页面的时候将js,css统一加载,部分页面按需加载;
- 不利于SEO:由于所有的内容都在一个页面中动态替换展示,所以SEO上有天然的弱势。
十一:new Vue() 发生了什么?
new Vue()
是创建了Vue实例,内部执行了根实例的初始化过程。
十二:Vue.use是干什么的?
vue.use
是用来使用插件的,我们可以在插件中扩展全局组件、指令、原型方法等。
十三:请说一下响应式数据的理解?
根据数据类型来做不同处理,数组和对象类型当值变化时劫持。
- 对象内部通过
defineReactive
方法,使用Object.defineProprety()
监听数据属性的get
来进行数据依赖收集,再通过set
来完成数据更新的派发;- 数组则通过重写数组方法来实现的,扩展它的7个变更方法,通过监听这些方法坐到依赖收集和派发更新;(push/pop/shift/unshift/splice/reverse/sort)
vue3中使用proxy来实现响应式数据的
十四:Vue是如何检测数组变化的?
数组考虑性能原因没有用
defineProprety
对数组的每一项进行拦截,而是选择重写数组方法以进行重写。当数组调用这7个方法(push/pop/shift/unshift/splice/reverse/sort
)时,执行ob.dep.notify()
进行派发通知Watcher
更新。
十五:Vue.$set方法是如何实现的?
给对象和数组本身都增加了
dep
属性,当给对象新增不存在的属性则触发对象依赖的watcher
去更新,当修改数组索引时我们调用数组本身的splice
方法去更新数组。
十六:Vue的模板编译原理?
template
模板转换成ast
语法树,.vue
文件中的template
是通过vue-loader
来处理的,并不是通过运行时的编译。- 对静态语法做静态标记。
- 重新生成代码。
模板引擎的实现原理就是
new Function + with
来实现的。
vue-loader中处理template属性主要靠的是vue-template-compiler
。
十七:$nextTick()
和 $forceUpdate()
与$set
的区别?
this.$nextTick():
- 数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进
this.$nextTick()
的回调函数中。函数执行在DOM渲染完之后。
this.$forceUpdate():
- 迫使Vue实例重新(rander)渲染虚拟DOM,注意并不是重新加载组件。结合
vue的生命周期
,调用$forceUpdate
后只会触发beforeUpdate和updated
这两个钩子函数,不会触发其他的钩子函数。它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
this.$set:
- 如果在vue实例创建之后添加新的属性到实例(data)上,它不会触发视图更新,用
this.$set
添加的属性会触发视图更新。
十八:v-if和v-show的区别?
v-if
是真正的条件渲染,知道条件第一次变为真时,才会开始渲染。
v-show
是不管初始条件是什么都会进行渲染,只是用于display
来进行显示隐藏。
总结:如果需要不停切换显示隐藏的建议用v-show
,不经常触发的用v-if
更加节省性能。
十九:watch、computed和methods的区别?
computed:计算属性,
依赖其他属性值
来进行计算,并且computed的值有缓存
,只有它依赖的属性值发生变化,computed才会重新计算。
watch:监听,监听数据的变化,
每当变化时都会执行回调
,进行后续的操作。
methods:是一个方法,methods
没有缓存机制
,每当重新触发渲染,调用方法会将函数再一次执行。
watch没有缓存
,监听的数据发生变化,会直接触发相应操作,但是支持异步。
而computed有缓存
,依赖数据发生变化时才会重新计算。
所以只有在执行异步或开销较大的操作时,才会使用watch
,否则用computed
。
注:
当一个属性受多个属性影响的时候就需要用到computed
。
当一条数据影响多条数据的时候就需要用watch
。
二十:v-model的原理?
v-model本质是一个语法糖,可以看成是
value+input
方法的语法糖。
可以通过model属性的prop
和event
属性来进行自定义。
vue的底层是采用数据劫持,结合发布-订阅模式的方法,通过
object.definePropert()
来劫持属性的setter
,getter
。
数据变动时发布消息给订阅者,触发响应的监听回调
二十一:watch的属性详解?
handle:watch中需要具体执行的方法
deep:深度监听,当需要监听一个对象的改变时,普通的
watch
方法无法监听到对象内部属性的改变,此时就需要deep
属性对对象进行深度监听。在选项参数中指定deep:true
。
immediate:
watch
时有一个特点,就是当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行。如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate
属性。在选项参数中指定immediate:true
。
// 举例
watch:{
cityName:{
handler(newName,oldName){
// ...
},
deep:true,
immediate:true
}
}
二十二:vue的插槽?
插槽就是子组件中提供给父组件使用的一个占位符,用
<slot></slot>
表示,父组件可以在这个占位符中填充任何模板代码,如HTML、组件等,填充的内容会替换掉子组件中的<slot></slot>
标签。
- 默认插槽:如果父组件没有传值到子组件,那子组件就用自己默认的内容显示在插槽上。
- 具名插槽:子组件中插槽的位置用名称命名好后,父组件要用
v-slot:
名称来显示在子组件中相对应的插槽。- 作用域插槽:作用域插槽其实就是带数据的插槽,
即带参数的插槽
,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传递过来的插槽数据来进行不同的方式展现和填充插槽内容。
二十三:vue常用命令?
v-model
/v-if
/v-else
/v-else-if
/v-show
/v-on
/v-bind
/v-html
/v-text
二十四:vue的性能优化?
- 尽量减少data中的数据。
- 防抖节流。
- key保证唯一性。
- 更多的情况下使用
v-if
代替v-show
。- spa页面采用
keep-alive
缓存组件。- 第三方模块按需引入。
- 图片懒加载。
- 使用
cdn
加载第三方模块。- 压缩代码。
二十五:vue-router与location.href的用法区别?
vue-router
使用pushState
进行路由更新,静态路由,页面不会重新加载;location.href
会触发浏览器,页面会重新加载一次。vue-router
使用diff
算法,实现按需加载,减少dom操作
。vue-router
是路由跳转或同一个页面跳转;location.href
是不同页面间跳转;vue-router
是异步加载this.$nextTick(()=>{获取url})
;location.href
是同步加载
二十六:vue的mixin?
mixin
可以定义公用的变量或方法,但是mixin
中的数据是不共享的,也就是每个组件中的mixin
实例都是不一样的,都是单独存在的个体,不存在相互影响的;mixin
混入对象值为函数的同名函数选项将会进行递归合并为数组,两个函数都会执行,只不过先执行mixin
中的同名函数;mixin
混入对象值为对象的同名对象将会进行替换,都优先执行组件内的同名对象,也就是组件内的同名对象将mixin
混入对象的同名对象进行覆盖;
二十七:vue阻止事件冒泡与js阻止事件冒泡?
- vue:
.stop
:阻止事件冒泡.prevent
:阻止默认事件- js:
.stopPropagation()
:阻止事件冒泡
.preventDefault()
:阻止默认事件
二十八:vue中的虚拟DOM
什么是虚拟DOM:用一个js对象来描述一个
DOM
节点。
- 为什么要有虚拟DOM:
- 因为
vue
是数据驱动视图的,数据发生变化视图就要随之更新,而操作真实DOM
是非常消耗性能的,因为浏览器把DOM
设计的非常复杂。- 虚拟DOM的用途:
- 要尽可能的少操作
DOM
,要通过对比数据的变化前后状态,计算出视图中哪些地方需要更新,用js
的计算性能来操作DOM
的性能,用js
模拟出一个DOM
节点,称之为虚拟DOM
节点。当数据发生变化的时候,我们对比变化前后的虚拟DOM
节点,通过DOM-Diff
算法计算出需要更新的地方,然后去更新需要更新的视图。- VNode类:
Vue
中就存在了一个VNode类
,通过这个类,我们就可以实例化出不同类型的虚拟DOM
节点。- VNode的作用:
- 在视图渲染之前,把写好的
template
模板先编译成VNode
并缓存下来,等到数据发生变化页面需要重新渲染的时候,再把数据发生变化后生成的VNode
与前一次缓存下来的VNode
进行对比,找出差异,然后有差异的VNode
对应真实的DOM
节点就是需要重新渲染的节点,根据有差异的VNode
创建出真实的DOM
节点再插入视图中,完成一次视图更新。
二十九:vue3.0有什么变化?
- 使用
proxy
实现响应式数据。api
进行变化,vue2
组件库与vue3
组件库不互通。- 创建
vue
实例用import {createApp} from 'vue'
,const app = createApp()
。- 删除掉了过滤器,建议使用方法替换或者计算属性。
三十:Vue3.x响应式数据原理?
Proxy
判断当前Reflect.get
的返回值是否为Object
,如果是则再通过reactive
方法做代理,这样就实现了深度观测。- 检测数组的时候可能触发多次
get
/set
,怎么防止触发多次?
可以判断key
是否为当前被代理对象target
自身属性,也可以判断旧值与新值是否相等,只有满足两个条件之一,才有可能执行trigger
。
三十一:Proxy与Object.defineProprety优劣对比?
优点:
Proxy
可以直接监听对象而非属性。Proxy
可以直接监听数组变化。Proxy
有多达13种拦截方法,不限于apply
、ovnKeys
、deleteProperty
、has
等等是Object.defineProprety
不具备的Proxy
返回的是一个新对象,而Object.defineProprety
只能遍历对象属性直接修改。Proxy
作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利。缺点:
Object.defineProprety
兼容性好,支持IE9
,而Proxy
存在浏览器兼容问题。
小程序
三十二:简单描述下微信小程序的相关文件类型?
WXML(WeiXin Markup Language)
是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。内部主要是微信自己定义的一套组件。WXSS(WeiXin Style Sheets)
是一套样式语言,用于描述WXML
的组件样式。js
逻辑处理,网络请求。json
小程序设置,如页面注册,页面标题及tabBar
。
app.json
必须要有这个文件,如果没有这个文件,项目无法运行,因为微信框架把这个作为配置文件入口,整个小程序的全局配置。包括页面注册
,网络设置,以及小程序的window背景色
,配置导航条样式
,配置默认标题
。
app.js
必须要有这个文件,没有也是会报错的。但是这个文件创建一下就行,什么都不需要写,以后我们可以在这个文件中监听并处理
小程序的生命周期
函数、声明全局变量
。
app.wxss
可选。
三十三:小程序的双向绑定和vue的有什么不一样?
小程序直接
this.data.a = 1
的属性是不可以直接同步到视图的,必须调用:this.setData({ a:1 })
三十四:小程序页面间有哪些传递数据的方法呢?
使用全局变量实现数据传递
在app.js
文件中定义全局变量globalData
,将需要存储的信息存放在里面。App({ // 全局变量 globalData:{ userInfo:null } })
使用的时候,直接使用
getApp()
拿到存储的信息。
使用
wx.navigateTo
与wx.redirectTo
的时候,可以将部分数据放在url
里面,并在新页面onLoad
的时候初始化。
注意:wx.navigateTo
和wx.redirectTo
不允许跳转到tab
所包含的页面。
注意:onLoad
只执行一次。
使用本地缓存
Storage
。
三十五:小程序的生命周期函数?
onLoad()
:页面加载时触发,只会调用一次。可获取当前页面路径的参数。onShow()
:页面显示时触发,一般用来发送数据请求。onReady()
:页面初次渲染完成时触发,只会调用一次。onHide()
:页面隐藏时触发。onUnload()
:页面卸载时触发。onPullDownRefresh()
:下拉刷新时触发。onReachBottom()
:上翻到底时触发。
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
- 全新的界面设计 ,将会带来全新的写作体验;
- 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
- 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
- 全新的 KaTeX数学公式 语法;
- 增加了支持甘特图的mermaid语法1 功能;
- 增加了 多屏幕编辑 Markdown文章功能;
- 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
- 增加了 检查列表 功能。
功能快捷键
撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
查找:Ctrl/Command + F
替换:Ctrl/Command + G
合理的创建标题,有助于目录的生成
直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC
语法后生成一个完美的目录。
如何改变文本的样式
强调文本 强调文本
加粗文本 加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
插入链接与图片
链接: link.
图片:
带尺寸的图片:
居中的图片:
居中并且带尺寸的图片:
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
如何插入一段漂亮的代码片
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
// An highlighted block
var foo = 'bar';
生成一个适合你的列表
- 项目
- 项目
- 项目
- 项目
- 项目1
- 项目2
- 项目3
- 计划任务
- 完成任务
创建一个表格
一个简单的表格是这么创建的:
项目 | Value |
---|---|
电脑 | $1600 |
手机 | $12 |
导管 | $1 |
设定内容居中、居左、居右
使用:---------:
居中
使用:----------
居左
使用----------:
居右
第一列 | 第二列 | 第三列 |
---|---|---|
第一列文本居中 | 第二列文本居右 | 第三列文本居左 |
SmartyPants
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE | ASCII | HTML |
---|---|---|
Single backticks | 'Isn't this fun?' | ‘Isn’t this fun?’ |
Quotes | "Isn't this fun?" | “Isn’t this fun?” |
Dashes | -- is en-dash, --- is em-dash | – is en-dash, — is em-dash |
创建一个自定义列表
-
Markdown
- Text-to- HTML conversion tool Authors
- John
- Luke
如何创建一个注脚
一个具有注脚的文本。2
注释也是必不可少的
Markdown将文本转换为 HTML。
KaTeX数学公式
您可以使用渲染LaTeX数学表达式 KaTeX:
Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N 是通过欧拉积分
Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞tz−1e−tdt.
你可以找到更多关于的信息 LaTeX 数学表达式here.
新的甘特图功能,丰富你的文章
- 关于 甘特图 语法,参考 这儿,
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:
这将产生一个流程图。:
- 关于 Mermaid 语法,参考 这儿,
FLowchart流程图
我们依旧会支持flowchart的流程图:
- 关于 Flowchart流程图 语法,参考 这儿.
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
注脚的解释 ↩︎