vue知识点
1、Vue的优点和缺点?
1.1、优点
渐进式、组件化,轻量级,虚拟dom
,响应式,单页面路由,数据与视图分开。
1.2、缺点
单页面不利于seo
,不支持IE8
以下,首屏加载时间过长。
2、为什么说Vue是渐进式框架?
渐进式:通俗点老讲就是,你想用啥就用啥,没有过多的强求;不用多做职责之外的事情。
3、Vue和React的异同点?
相同点:
- 1、都是用了虚拟
dom
。
- 2、组件化开发。
- 3、都是单向数据流(父子组件之间,不建议子修改父传下来的数据)。
- 4、都支持服务端渲染。
不同点:
- 1、
React
的JSX
,Vue
的template
。
- 2、数据变化,
React
手动(setState),Vue
自动(初始化已做响应式处理,Object.defineProperty
)。
- 3、
React
单向绑定,Vue
双向绑定。
- 4、
React
的Redux
,Vue
的Vuex
。
4、Vue和JQuery的区别在哪?为什么放弃JQuery用Vue
- 1、
JQuery
是直接操作DOM
,Vue
不直接操作DOM
,Vue
的数据和视图是分开的,Vue
只需要操作数据即可。
- 2、在操作
DOM
频繁的场景里,JQuery
的操作DOM
行为是频繁的,而Vue
利用虚拟DOM
技术,大大提高了更新DOM
时的性能。
- 3、
Vue
中不提倡直接操作DOM
,开发者只需要把大部分精力放在数据层面上。
- 4、
Vue
集成了一些库,大大提高了开发效率。比如Vuex
、Router
等。
5、为什么data是个函数并且返回一个对象呢?
data
之所以是一个函数,是因为一个组件可能会多处调用,而每一次调用都会执行data
函数并返回一个新的数据对象,这样可以避免多处调用之间的数据污染。
6、组件之间的传值方式有哪些?
- 父组件传值给子组件,子组件使用
props
进行接收。
- 子组件传值给父组件,子组件使用
$emit+事件对父组件进行传值
。
- 组件中可以使用
$parent
和$children
获取到父组件实例和子组件实例,进而获取数据。
- 使用
¥attrs
和$listeners
,在对一些组件进行二次封装的时候可以方便传值,例如A->B->C。
- 使用
$refs
获取组件实例,进而获取数据。
- 使用
Vuex
进行状态管理。
- 使用
eventBus
进行跨组件触发事件,进而传递数据。
- 使用
provide
和inject
,官方建议我们不要用这个,我在看ElementUI源码时发现大量使用。
- 使用浏览器本地缓存,例如
localStorage
。
7、 路由有哪些模式呢?又有什么不同呢?
-
hash
模式:通过#
号后面的内容的更改,触发 hashchange
事件,实现路由切换。
-
history
模式:通过pushState
和replaceState
切换url
,实现路由切换,需要后端配合
8、 如何设置动态class,动态style?
9、v-if 和v-show有何区别?
- 1、
v-if
是通过控制dom
元素的删除和生成来实现显隐,每一次显隐都会使组件重新跑一遍生命周期,因为显隐决定了组件的生成和销毁.
- 2、
v-show
是通过控制dom
元素的css
样式来实现显隐,不会销毁。
- 3、频繁或者大数量显隐使用
v-show
,否则使用v-if
。
10、computed 和 watch 有何区别?
- 1、
computed
是依赖已有的变量来计算一个目标变量,大多数情况都是多个变量凑在一起计算出一个变量,并且computed
具有缓存机制,依赖值不变的情况下其会直接读取缓存进行复用,computed
不能进行异步操作。
- 2、
watch
是监听某一个变量的变化,并执行相应的回调函数,通常是一个变量的变化決定多个变量的变化,watch
可以进行异步操作。
- 3、简单记就是:一般情况下
computed
是多对一,watch
是一对多。
11、 为什么v-if和v-for不建议用在同一标签?
在vue2中,v-for
优先级是高于v-if
的,咱们来看例子
{item}}
上面的写法是v-for
和v-if
同时存在,会先把7个元素都遍历出来,然后再一个个判断是否为3,并把3给隐藏掉,这样的坏处就是,渲染了无用的3节点,增加无用的dom
操作,建议使用computed
来解决这个问题:
{{item}}
computed({
list(){
return [1, 2, 3, 4, 5, 6, 7].filter (item => item!== 3)
}
}
12、watch有哪些属性,分别有什么用?
当我们监听一个基本数据类型时:
watch:{
value(){
//do something
}
}
当我们监听一个引用数据类型时:
watch:{
obj:{
handler(){//执行回调
//do something
},
deep:true,//是否进行深度监听
immediate:true//是否初始执行handler函数
}
}
13、父子组件生命周期顺序
父beforeCreate
-> 父created
-> 父beforeMount
-> 子beforeCreate
-> 子created
-> 子beforeMount
-> 子mounted
-> 父mounted
。
14、对象新属性无法更新视图,删除属性无法更新视图,为什么?怎么办?
- 原因:
Object.defineProperty
没有对对象的新属性进行属性劫持。
- 对象新属性无法更新视图:使用
Vue.$set(obj,key,value)
。
- 删除属性无法更新视图:使用
Vue.$delete(obj,key)
,组件中this.$delect(obj.key)
。
15、直接arr[index] = xxx 无法更新视图怎么办?为什么?怎么解决?
- 原因:Vue没有对数组进行
Object.defineProperty
的属性劫持,所以直接arr[index] = xxx
是无法更新视图的。
- 使用数组的
splice
方法,arr.splice(index,1,item)
。
- 使用
Vue.$set(arr,index,value)
。
16、vue 的SSR 是什么?有什么好处?
-
SSR
就是服务端渲染。
- 基于
nodejs serve
服务环境开发,所有html
代码在服务端渲染。
- 数据返回给前端,然后前端进行“激活”,即可成为浏览器识别的
html
代码。
-
SSR
首次加载更快,有更好的用户体验,有更好的seo
优化,因为爬虫能看到整个页面的内容如果是vue
项目,由于数据还要经过解析,这就造成爬虫并不会等待你的数据加载完成,所以其实vue 项的
seo
体验并不是很好。
17、 vue 响应式是怎么实现的?
整体思路是数据劫持+观察者模式
对象内部通过defineReactive
方法,使用Object.defineProperty
将属性进行劫持 (只会劫持已经存在的属性),数组则是通过重写数组方法来实现。当页面使用对应属性时,每个属性都拥有自己的dep
属性,存放他所依赖的watcher (依赖收集)
,当属性变化后会通知自己对应的watcher
去更新(派发更新)。
18、 为什么只对对象劫持,而要对数组进行方法重写?
因为对象最多也就几十个属性,拦截起来数量不多,但是数组可能会有几百几千项,拦截起来非常耗性能,所以直接重写数组原型上的方法,是比较节省性能的方案。
19、vue.set方法的原理?
function set (target, key, val) {
//判断是否是数组
if (Array.isArray (target)) {
//判断谁大谁小
target.length = Math.max(target.length,key)
//执行 splice
target.splice (key, 1, val)
return val
}
const ob = target.__ob__
//如果此对象没有不是响应式对象,直接设置并返回
if (key in target && ! (key in target.prototype) || !ob){
target[key] = val
return val
//否则,新增属性,并响应式处理
defineReactive (target, key, val)
return val
}
20、如果子组件改变props 里的数据会发生什么?
- 改变的
props
数据是基本类型
如果修改的是基本类型,则会报错
props: {
num: Number,
}
created(){
this.num = 999
}
Ietvuc wornJ : Avoid rucatins a prop cirectiy since the voiuc wsll oe overaritten wncnever she parent cotponcnt re-renacrs• insteoa, use a aoti
props: {
item: {
default: () => ({})
}
}
created{}
//不报错,并且父级数据会跟着变
this.item.name ='sanxin';
//会报错,跟基础类型报错一样
this.item = 'sss'
}
21、props怎么自定义验证?
props: {
num: {
default: 1.
validator: function (value) {
//返回值为false 则验证不通过,报错
return{
[1, 2, 3, 4, 5].indexOf (value) !== -1
}
}
}
22、watch的immediate 属性有什么用?
比如平时created
时要请求一次数据,并且当搜索值改变,也要请求数据,我们会这么写:
created{
this.getList()
},
watch: {
searchInputvalue(){
this.getList()
}
}
使用immediate
完全可以这么写,当它为true
时,会初始执行一次
watch: {
searchInputValue:{
handler: 'getList',
immediate:true
}
}
23、计算变量时,methods 和computed 哪个好?
{{howMuch1()}}
{{howMuch}2}
{{findex}}
data: () {
return {
index: 0
}
},
methods: {
howMuch1(){
return this.num + this.price
}
},
computed: {
howMuch2() {
return this.num + this.price
}
}
computed
会好一些,因为computed
会有缓存。例如index
由0变成1,那么会触发视图更新,这时候methods
会重新执行一次,而computed
不会,因为computed
依赖的两个变量num和price都没变。
24、如何将获取 data 中某一个数据的初始状态?
在开发中,有时候需要拿初始状态去计算。例如
data(){
return{
num: 10
}
}
mounted(){
this.num = 1000
}
methods: {
howMuch(){
//计算出num增加了多少,那就是1000-初始值
//可以通过 this. $options.data0.xxx 来获取初始值
console.log(1000 - this.$options.data().num)
}
}
25、自定义v-model
默认情况下,v-model
是@input
事件侦听器和:value
属性上的语法糖。但是,你可以在你的vue 组件中指定一个模型属性来定义使用什么事件和value属性。
export default: {
model: {
event: 'change',
prop: 'checked'
}
}
26、相同的路由组件如何重新渲染?
开发人员经常遇到的情况是,多个路由解析为同一个vue
组件。问题是,vue
出于性能原因默认情况下共享组件将不会重新渲染,如果你尝试在使用相同组件的路由之间进行切换,则不会发生任何变化。
const routes = [
{
path: "/a",
component: MyComponent
},
{
path: "/b",
component: MyComponent
},];
如果依然想重新渲染,怎么办呢?可以使用key