题目

2022-03-10

2022-03-08  本文已影响0人  如果俞天阳会飞

一 vue

vue的优点?

vue的缺点?

为什么说Vue是一个渐进式框架?

Vue的全家桶,你可以选择不用,或者只选几样去用,比如不用vuex
根据场景,官方提供了方便的框架供你使用

Vue跟React的异同点?

相同点:
不同点:

MVVM是什么?和MVC有何区别呢?

MVC

MVVM

组件中的data是个函数并且返回一个对象呢?

组件是用来复用的, js 的对象是引用关系,如果组件中的data是一个对象,这样作用域没有隔离,子组件中的data属性值会互相影响

使用过哪些Vue的修饰符呢?

这样理解vue单向数据流?

父组件传输props给子组件时,子组件只能使用不能修改,这是为了组件之间更好的去解耦.比如有一个父组件,传props给10个子组件,如果某一个子组件修改了,那么会影响其它9个子组件跟着刷新,所以不推荐子组件修改props

组件之间的通信方式都有哪些,用过eventBus,eventbus的是想是什么

写个自定义 v-model?

v-model实际是:value + @input的语法糖

<input v-model="inputValue" />

<input 
:value="inputValue" 
@input="inputValue = $event.target.value" 
/>

attrs 和 $listener 有了解吗?

常用于对组件进行二次封装时,比如A -> B -> C,B可以直接将爷爷组件的所有数据或者事件直接传给孙子

Vue 生命周期有哪些,都是做什么的,updated 什么情况下会触发,beforeCreate 的时候能拿到 Vue 实例么,组件销毁的时候调用的是哪个 API

什么情况下会触发组件销毁,销毁的时候会卸载自定义事件和原生事件么?

组件销毁时会自动卸载组件本身绑定的事件,但是仅限于组件本身。例如一些定时器、全局对象的事件绑定、eventBus则不会自动解绑,需要手动解绑。

自定义指令写过么,自定义指令都有哪些钩子?

vue2
vue3

Vue2 的数据响应式有两个缺陷,你知道是哪两个缺陷么,为什么会有这样的缺陷,如何解决?

vue 如何实现对数组的监听,为什么vue没有对数组下标修改做劫持?

vue2是通过重写了数组原型上的方法来达到对数组的修改的监听,vue2没有对数组下标做劫持,是出于心梗的考虑,因为通常数组元素都是非常多的,可能成百上千,如果每个元素都进行劫持,则非常耗费性能。

路由的几种模式?

路由的钩子函数?

全局钩子

beforeEach:跳转路由前

afterEach:路由跳转后

路由独享钩子
routes: [
  {
    path: '/xxx',
    component: xxx,
    beforeEnter: (to, from, next) => {
      
    }
  }
]
组件内路由钩子

使用过哪些Vue的内部指令呢?

v-if和v-show有何区别?

computed和watch有何区别?

computed

计算属性将会混入到Vue的实例当中,所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。

watch

为什么v-if和v-for不建议用在同一个标签上?

v-for的优先级高于v-if每项都通过v-for渲染出来后再去通过v-if判断显隐,做了很多无用功

uex的有哪些属性?用处是什么?

不需要响应式的数据应该怎么处理?

watch有哪些属性,分别有什么用?

父子组件生命周期顺序?

1.父beforeCreate --> 2.父created --> 3.父beforeMount --->
4.子beforeCreate --> 5.子created ---> 6.子beforeMount ---->
7.子mounted ----> 8.父mounted

对象新属性无法更新视图,删除属性无法更新视图,为什么?怎么办?

直接arr[index] = xxx无法更新视图怎么办?为什么?怎么办?

  1. splice:arr.splice(index, 1, value)
  2. Vue.set(target, index, value)

nextTick的原理?

维护一个数组,每次调用时讲回调函数压入这个数组,然后优先选择微任务,在微任务回调中去执行数组中的所有回调,同时维护一个布尔值,确保每一次队列进行一次执行数组所有回调

let callbacks = []; //回调函数
let pending = false;
function flushCallbacks() {
  pending = false; //把标志还原为false
  // 依次执行回调
  for (let i = 0; i < callbacks.length; i++) {
    callbacks[i]();
  }
}
let timerFunc; //先采用微任务并按照优先级优雅降级的方式实现异步刷新
if (typeof Promise !== "undefined") {
  // 如果支持promise
  const p = Promise.resolve();
  timerFunc = () => {
    p.then(flushCallbacks);
  };
} else if (typeof MutationObserver !== "undefined") {
  // MutationObserver 主要是监听dom变化 也是一个异步方法
  let counter = 1;
  const observer = new MutationObserver(flushCallbacks);
  const textNode = document.createTextNode(String(counter));
  observer.observe(textNode, {
    characterData: true,
  });
  timerFunc = () => {
    counter = (counter + 1) % 2;
    textNode.data = String(counter);
  };
} else if (typeof setImmediate !== "undefined") {
  // 如果前面都不支持 判断setImmediate
  timerFunc = () => {
    setImmediate(flushCallbacks);
  };
} else {
  // 最后降级采用setTimeout
  timerFunc = () => {
    setTimeout(flushCallbacks, 0);
  };
}

export function nextTick(cb) {
  callbacks.push(cb);
  if (!pending) {
    pending = true;
    timerFunc();
  }
}

审查元素时发现data-v-xxxxx,这是啥?

样式模块化scoped的效果,在本组件的标签都会带上data-v-xxx的属性,然后通过属性选择器实现样式模块化的效果

provide 和inject是响应式的吗?

引用数据类型是响应式,基础数据类型不响应式

自定义v-model

export default {
model: {
   event: 'change',
   prop: 'checked'
}
}

为什么不建议用index做key,为什么不建议用随机数做key?

举个例子:

<div v-for="(item, index) in list" :key="index">{{item.name}}</div>

list: [
    { name: '小明', id: '123' },
    { name: '小红', id: '124' },
    { name: '小花', id: '125' }
]

渲染为
<div key="0">小明</div>
<div key="1">小红</div>
<div key="2">小花</div>

现在我执行 list.unshift({ name: '小林', id: '122' })

渲染为
<div key="0">小林</div>
<div key="1">小明</div>
<div key="2">小红</div>
<div key="3">小花</div>


新旧对比

<div key="0">小明</div>  <div key="0">小林</div>
<div key="1">小红</div>  <div key="1">小明</div>
<div key="2">小花</div>  <div key="2">小红</div>
                         <div key="3">小花</div>

可以看出,如果用index做key的话,其实是更新了原有的三项,并新增了小花,虽然达到了渲染目的,但是损耗性能

现在我们使用id来做key,渲染为

<div key="123">小明</div>
<div key="124">小红</div>
<div key="125">小花</div>

现在我执行 list.unshift({ name: '小林', id: '122' }),渲染为

<div key="122">小林</div>
<div key="123">小明</div>
<div key="124">小红</div>
<div key="125">小花</div>

新旧对比

                           <div key="122">小林</div>
<div key="123">小明</div>  <div key="123">小明</div>
<div key="124">小红</div>  <div key="124">小红</div>
<div key="125">小花</div>  <div key="125">小花</div>

可以看出,原有的三项都不变,只是新增了小林这个人,这才是最理想的结果

插槽的使用以及原理?

普通插槽 普通插槽slot会被当做子元素进行解析,最终会被解析成一个_t函数,他接收的第一个参数为插槽的名称,默认是default,也就是_t('default'),执行此函数进行最终元素的渲染,如果是具名插槽,则传对应的插槽名 作用域插槽 插槽会被封装成一个函数放置在scopeSlotes对象中,解析时_t第二个参数接收子组件的数据,并进行渲染

说说nextTick的用处?

修改数据时不能马上得到最新的DOM信息,所以需要使用nextTick,在nectTick回调中可以获取最新DOM信息

vue的hook的使用?

同一组件中使用

这是我们常用的使用定时器的方式

export default{
  data(){
    timer:null  
  },
  mounted(){
      this.timer = setInterval(()=>{
      //具体执行内容
      console.log('1');
    },1000);
  }
  beforeDestory(){
    clearInterval(this.timer);
    this.timer = null;
  }
}

上面做法不好的地方在于:得全局多定义一个timer变量,可以使用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...
  }
},

三 ES6

Symbol 有了解吗,迭代器有了解吗,哪些是可迭代的?

是ES6的特性,具体使用场景有:

symbol
迭代

迭代器:Iterator,可迭代对象有Array、Set、Map,想将不可迭代对象变成可迭代对象,可以设置Symbol.iterator属性

const t = {
  name: '林三心',
  age: 12
}

t[Symbol.iterator] = function () {
  let index = 0,
    self = this,
    keys = Object.keys(this)

  return {
    next() {
      if (index < keys.length) {
        return {
          value: self[keys[index++]],
          done: false
        }
      } else {
        return {
          value: undefined,
          done: true
        }
      }
    }
  }
}
for (let value of t) {
  console.log(value)
}

用Set获取两个数组的交集,如何做?

合集
const heji = (arr1, arr2) => {
  return [...new Set(arr1.concat(arr2))]
}

交集
const jiaoji = (arr1, arr2) => {
  const temp = new Set(arr1)
  return Array.from(new Set(arr2)).filter(item => {
    return temp.has(item)
  })
}
差集
const chaji = (arr1, arr2) => {
  const temp1 = new Set(arr1)
  const temp2 = new Set(arr2)
  const res = []
  for (let item of temp1) {
    !temp2.has(item) && res.push(item)
  }
  return res
}

实现 Promise.all?

Promise.sx_all = (promises) => {
    return new Promise((resolve, reject) => {
        const result = []
        let count = 0
        for (let i = 0; i < promises.length; i++) {
            const promise = Promise.resolve(promises[i])
            promise.then(res => {
                result[i] = res
                count++
                if (count === promises.length) {
                    resolve(result)
                }
            }).catch(err => {
                reject(err)
            })
        }
    })
}

animation 和 transition 的区别?

来源: https://mp.weixin.qq.com/s/Gb_sTNP45T21LHAYk0QXaQ

上一篇 下一篇

猜你喜欢

热点阅读