1. vue2.x 生命周期
1.1 系统自带有哪些?
创建阶段
- beforeCreate
- created
- beforeMount
- mounted
运行阶段
- beforeUpdate
- updated
销毁阶段
- beforeDestroy
- destroyed
1.2 一旦进入组件或页面,会执行哪些生命周期,并且它们的顺序?(见上图)
- 我们只需关注进入页面或组件,不进行任何操作,会执行哪些生命周期,并且它们的顺序?
- beforeCreate
- created
- beforeMount
- mounted
1.3 在哪个阶段有$el(dom节点),在哪个阶段有$data(data节点)
- beforeCreate 都没有
- created 有
$data,无$el(即还没有dom节点) - beforeMount 有
$data,无$el - mounted 都有(所以到了mounted中才有dom节点)
1.4 如果是加了keep-alive 会多了两个生命周期
- activated被 keep-alive 缓存的组件激活时调用
- deactivated被 keep-alive 缓存的组件失活时调用
1.5 如果是加了 keep-alive,第一次进入组件会执行哪些生命周期?
- beforeCreate
- created
- beforeMount
- mounted
- activated
1.6 如果是加了 keep-alive,第二次进入组件会执行哪些生命周期后者第N次进入组件会执行哪些生命周期?
- activated 只执行这一个生命周期
2. 谈谈你对 keep-alive的了解?
- 是什么?
keep-alive是vue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM
- 使用场景
可以少网络请求,如果当前组件数据量比较大,就可以节省网络请求 >> 提升用户体验
- 举例
如果详情页面之间进行切换,就可以使用
keep-alive进行缓存组件,防止同样的数据重复请求
3. v-if 和 v-show 的区别?
- 实现原理不同:
- v-if指令会动态创建或移除DOM元素,从而控制元素在页面上的显示与隐藏
- v-show指令会动态为元素添加或移除 display:none样式,从而控制元素的显示与隐藏
- 使用场景不同:
- 初次加载或切换次数少 v-if 更好,页面不会做加载盒子
- 频繁切换,v-show更好,显示和隐藏消耗性能更少
4. v-if 和 v-for 优先级
v-for的优先级要比 v-if 高
5. ref是什么?
来获取dom元素和组件的引用
<h1 ref="myh1"> ref</h1>
console.log(this.$ref.myh1)
6. nextTick是什么?
- 是什么?
- 获取数据更新后的dom内容
- 如果你在数据改变之后的操作跟改变之后的DOM有关,那么就应该使用this.$nextTick()
- 使用场景
场景一:点击按钮展示输入框并获取焦点
<template>
<div>
<!-- 场景二:点击按钮原本隐藏的输入框,显示出来,并获取焦点 -->
<input type="text" v-show="isShow" ref="focusRef" />
<button @click="showIpt">展示输入框并获取焦点</button>
</div>
</template>
<script>
export default {
name: 'TestDemo2',
data() {
return {
isShow: false
}
},
methods: {
showIpt() {
this.isShow = true
// 即此时数据发生了变化,但是 input 输入框的 display 属性仍是 之前的 none 而不是最新的 block
console.log(this.$refs.focusRef.style.display) // none
// 没有报错,但是也没拿到焦点,因为 此时拿到的 display 是 none input 输入框都隐藏了,怎么能拿到焦点呢?
// this.$refs.focusRef.focus()
this.$nextTick(() => {
this.$refs.focusRef.focus()
})
}
}
}
</script>
场景二:数据的增加和删除
<div>
<div>
<ul>
<li ref="liNode" v-for="(item, index) in liList" :key="index">
{{ item }}
</li>
</ul>
</div>
<button @click="addOneData">增加一条数据</button>
<b>当前li长度为===〉{{ currLiLenth }}</b>
</div>
</template>
<script>
export default {
data() {
return {
liList: ['java', 'js', 'c'],
// liList 数组的长度,默认为 0
currLiLenth: 0
}
},
created() {
this.currLiLenth = this.liList.length
},
methods: {
//增加一条li数据
addOneData() {
// 点击按钮,向 liList 数组追加值
this.liList.push(1)
// // 得到最新长度的数组的值,这种方式有问题
// this.currLiLenth = this.$refs.liNode.length
// // 添加后一条数据,此时数组 length 应该为 4
// // 但是结果为三,原因在与 data 数组中数据的更新没来及同步到 dom 结构上
// console.log(this.$refs.liNode.length) // 3
//使用nextTick进行更新dom,会在dom更新之后的下一次进行回调
this.$nextTick(() => {
this.currLiLenth = this.$refs.liNode.length
})
}
}
}
</script>
7. scoped原理
- 作用:让样式在本组件中生效,不影响其他组件
- 原理:给节点新增自定义属性,然后css根据属性选择器添加样式
8. vue中如何做到样式穿透?
vue中针对不同的样式类型(css,less,scss)有不用的样式穿透方法。
css使用>>>less使用/deep/scss使用::v-deep
1. css
<style scoped>
>>> .c1 .c2{
color: green !important;
}
</style>
2. less
<style scoped lang="less">
/deep/ .c1 .c2{
color: green !important;
}
</style>
3. scss
<style scoped lang=”scss“>
::v-deep .c1 .c2{
color: green !important;
}
</style>
9. vue组件之间如何传值通信?
9.1 父组件传值子组件
父组件向子组件共享数据需要使用自定义属性
9.2 子组件传值父组件
子组件向父组件共享数据使用自定义事件
9.3 兄弟组件之间的传值
vue2.x 中,兄弟组件之间数据共享的方案是 EventBus
9.4 通过 vuex
10. computed、methods、watch 有什么区别?
- methods: 方法表示一个具体的操作,主要是书写业务逻辑(没有缓存)
- computed: 计算属性会缓存计算的结果,只有计算属性依赖的数据变化时,才会重新进行运算
- watch VS computed
computed 侧重于监听多个值的变化,最终计算并返回一个新值
watch 侧重于监听单个数据的变化,最终执行特定的业务操作,不需要任何返回值(场景:检测用户名是否可用)
11. props 和 data 优先级谁高?
props--> methods--> data--> computed--> watch
12. Vuex相关的面试题
12.1 Vuex有哪些属性?
- state 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 state 中进行存储 (类似Vue中的data)
- mutations 用于变更 Store中的数据 (类似 Vue 中的methods)
- actions 用于处理异步任务(提交mutations的)
- getters 类似于 Vue 中的计算属性
- modules 把以上四个属性再细分,让仓库更好管理
12.2 Vuex是单向数据流还是双向数据流?
- Vuex是单向数据流
12.3 Vuex的 mutations 和 actions 的区别?
- mutations中的方法可以直接修改state数据,actions是异步执行mutations中的方法,所以它俩都可以改数据,区别是:mutations是执行同步操作,actions 是执行异步操作。
12.4 Vuex如何做持久化存储?(vuex数据是存在内存中的,当页面刷新时,state中的数据会丢失)
使用localStorage自己写
使用数据持久化 vuex-persistedstate 插件
13. Vue设置代理(通过代理转发解决跨域问题 )
在vue.config.js 中 设置 devServer.proxy
devServer:{
proxy:{
'/api':{//表示拦截以/api开头的请求路径
target:'http://(这里填你项目真实的后端地址)',
changOrigin: true,//是否开启跨域
pathRewrite:{
'^/api':'' //重写api,把api变成空字符,因为我们真正请求的路径是没有api的
}
}
}
}
// main.js
axios.defaults.baseURL = '/api'
14. 打包路径(当项目打包后,打开页面是空白的问题)
// 在 vue.cofig.js 中,设置如下代码
module.exports = {
publicPath:'./'
}
// 2. vue 路由模式是 history || hash,前端如果是自己测试项目,改为 hash,才会完全展示页面
// 2.1 项目上线要求是 history 模式,如何做? 让后端做重定向
15. Vue 接口环境设置
16. v-model双向绑定原理(在Vue源码中体现的)
- 通过 Object.defineProperty劫持数据发生的改变,如果数据发生了改变,触发update方法,进行更新节点内容,从而实现了数据双向绑定的原理