vue成神之路
一、荣耀黄金
1.vue的优点?缺点?
优点:渐进式,组件化,轻量,虚拟dom,响应式,单页面路由,数据试图分离
缺点:首屏加载时间长
2.vue和react的异同点
相同点:
1.都使用了虚拟dom
2.组件化开发
3.都是单向数据流(父子组件之间,不建议子组件修改父组件传下来的数据)
4.都支持服务端渲染
不同点:
1.react的jsx,vue的template
2.数据变化,react手动,vue自动
3.react单向绑定,vue双向绑定
4.react的redux,vue的vuex
3.为什么data是一个函数并且返回一个对象呢?
data之所以是一个函数,是因为一个组件可能回多处调用,而每次调用就会执行data函数并且返回新的对象,这样可以避免数据污染
4.vue的修饰符
- .lazy:作用是,改变输入框的值是value不会改变,当光标离开输入框时,v-model绑定的值value才会改变
- .trim:作用类似于js中trim()方法,作用时v-model绑定的值的首尾空格给过滤带哦
- .number:作用将值转化成数字,到那时先输入字符串和先输入数字,是两种情况,先输入数字的化,只能取前面数字部分,先输入字母的化,number修饰符无效
- .stop阻止冒泡
- .prevent 作用时阻止默认事件
- .once作用是事件值执行一次
5.vue内部指令
v-text,v-html,v-show,v-if,v-else,v-else-if,v-for,v-on,v-bind,v-model,v-slot,v-once:组件和元素值渲染一次,v-pre:跳过这个元素和他子元素的编译过程
6.组件间传值的方法有哪些
- 父组件向子组件,子组件使用props进行接收
- 子组件向父组件,子组件通过$emit触发自定义事件利用参数传值
- 组件中可以使用$parent和$children获取父组件实例和子组件实例,进而获取数据
- 使用$attrs和$listeners,在对一些组件进行二次封装饰方便传值,例如a-b-c
- 使用$refs获取组件实例,进而获取数据
- 使用vuex进行状态管理
- 使用eventBus进行跨组件间触发事件进而传递数据
- 使用provide和inject
- 使用本地缓存
7.路由有那些模式?有什么不同
1.hash模式:通过#号后面的内容的更改,触发hashchange事件,实现路由奇幻
2.history模式:通过pushState和replaceState切换url,触发popstate事件,实现路由切换,需要后端配合
8.是指动态的class,动态的style>
- 动态class对象:<div :class="{'is-active':true,'red':isRed}"></div>
- 动态class数组:<div :class="['is-active',isRed'?'red':'']"></div>
9.computed和watch有何区别
- computed是依赖已有的变量计算一个目标变量,大多数情况都是多个变量凑到一起,并且computed具有缓存机制,依赖值不变的情况下会直接读取缓存进行复用,computed不能进行异步操作
- watch是监听一个变量的变化,并只想相应的回调函数通常是一个变量的变化决定多个变量的变化,watch可以进行异步操作
10.为什么v-if和v-for不建议用在同一个标签
在vue2中v-for的优先级是高于v-if的,例如
<div v-for="item in [1, 2, 3, 4, 5, 6, 7]" v-if="item !== 3"> {{item}} </div>
上面的写法v-for和v-if同时存在,会把7个元素都便利出来,然后再一个个判断是否为3,并把3给隐藏掉,这样的坏处渲染了无用的3节点,增加无用的dom操作,可以采用计算属性来解决这个问题
<div v-for="item in list"> {{item}} </div> computed() { list() { return [1, 2, 3, 4, 5, 6, 7].filter(item => item !== 3) } }
11.vuex的有那些属性,用处
- state:定义了应用状态的数据结构,可以再这里设置默认的初始状态
- getter:允许组件从store中获取数据,mapgetters辅助函数仅仅是将store中的getter映射到局部计算属性
- mutation:是唯一更改store中状态的方法且必须是同步函数
- action:用于提交mutation,而不是直接变更状态,可以包含任意异步操作。
- module:允许将单一的store拆分为多个srore且同时保存在单一的状态树中
二、铂金
1.不需要响应式的数据应该怎样处理?
在我们的vue开发中,会有一些数据,从始至终都未曾改变过,这种死数据,不需要响应式处理,不然只会做一些无用功
// 方法一:将数据定义在data之外 data () { this.list1 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx } return {} } // 方法二:Object.freeze()冻结 data () { return { list1: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}), } }
2.watch有那些属性,分别有什么用
当我们要监听一个引用数据类型时:
watch:{ obj:{ handler(){//执行回调 } deep:true,//是否进行深度监听 immediate:true,//是否初始执行handler函数 } }
3.父子组件生命周期的顺序
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
4.vue自定义指令
5.为啥不建议index做key,为啥不建议用随机数来key?
可以看出,如果使用index作为key,更新原有值时虽然达到渲染目的,但是是全部更新,损耗性能,用唯一id的化之新增对应项
6.说说nextTick的用处?
我没要修改变量的值,是没修改一次,dom就更新一次吗?不是的,vue采用的是异步更新的策略,通俗点说就是,统一事件循环内多次修改,会统一进行一次试图更新,这样才能节省性能,
vue异步更新,所以数据一更新,试图却还没有更新,想要拿到最新的试图数据this.$nextTick(() => { console.log(this.$refs.testDiv.innerHTML) // 林三心 })
三、永恒钻石
1.vue响应式是怎么实现的?
整体思路是数据劫持+观察者模式
对象内部通过defineReactive方法,使用Objct.defineProperty将属性进行劫持,数组则是通过重写数组方法来实现。当页面使用对应属性时,每个属性都拥有自己的dep属性,存放他所依赖的watcher(依赖收集),当属性变化后会通知自己对应的watcher去更新
2.为啥只对对象劫持,二要对数组进行方法重写
应为对象最多也就几十个属性,拦截起来数量不多,但是数组可能会有很多,拦截起来非常消耗性能,所以直接重写数组原型是的方法,是一个比较节省性能的方案
四、冷门知识
1.如果子组件改变props里面的数据会发生什么,
改变的props数据是基本数据类型,会报错,改变props数据是引用类型,不会报错,并且父级的数据会跟这改变
2.props怎样自定义验证
props:{
num:{
defaulet:1,
validator:function(value){
//返回值为false则不通过,报错
return [
1,2,3,4,5
].indexOf(value)!==-1
}
}
}
3.审查元素时发现data-v-xxx,是啥
这是在标记vue文件中css时使用scoped标记的,应为要保证各文件中的css不相互影响,给每个component都做了唯一的标记,所以每引用一个component就会出现一个新的’data-v-xxx‘标记
4.computed如何实现传参
// html <div>{{ total(3) }} // js computed: { total() { return function(n) { return n * this.num } }, } 返回一个函数
5.vue中hook的使用
平常使用定时器 export default{ data(){ timer:null }, mounted(){ this.timer = setInterval(()=>{ //具体执行内容 console.log('1'); },1000); } beforeDestory(){ clearInterval(this.timer); this.timer = null; } } 需要多定义一个变量,使用hook export default{ methods:{ fn(){ let timer = setInterval(()=>{ //具体执行代码 console.log('1'); },1000); this.$once('hook:beforeDestroy',()=>{ clearInterval(timer); timer = null; }) } } } 。
父子组件中使用
如果子组件需要在mounted时触发父组件的某一个函数,平时都会这么写://父组件 <rl-child @childMounted="childMountedHandle" /> method () { childMountedHandle() { // do something... } }, // 子组件 mounted () { this.$emit('childMounted') }, 使用hook的话可以更方便: //父组件 <rl-child @hook:mounted="childMountedHandle" /> method () { childMountedHandle() { // do something... } },
6.provide和inject是响应式吗
基本数据类型无法实现响应式
7.动态指令和参数
<template> ... <aButton @[someEvent]="handleSomeEvent()" :[someProps]="1000" />... </template> <script> ... data(){ return{ ... someEvent: someCondition ? "click" : "dbclick", someProps: someCondition ? "num" : "price" } }, methods: { handleSomeEvent(){ // handle some event } } </script>
8.计算变量是,methods和computed那个好
computed会好一些,应为computed会有缓存。