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的修饰符

  1. .lazy:作用是,改变输入框的值是value不会改变,当光标离开输入框时,v-model绑定的值value才会改变
  2. .trim:作用类似于js中trim()方法,作用时v-model绑定的值的首尾空格给过滤带哦
  3. .number:作用将值转化成数字,到那时先输入字符串和先输入数字,是两种情况,先输入数字的化,只能取前面数字部分,先输入字母的化,number修饰符无效
  4. .stop阻止冒泡
  5. .prevent 作用时阻止默认事件
  6. .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有何区别

  1. computed是依赖已有的变量计算一个目标变量,大多数情况都是多个变量凑到一起,并且computed具有缓存机制,依赖值不变的情况下会直接读取缓存进行复用,computed不能进行异步操作
  2. 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会有缓存。

posted @ 2022-01-21 12:00  前端乔  阅读(112)  评论(0编辑  收藏  举报