Vue----总结(面试、开发)全靠它

283 阅读1分钟

vueCli搭建Vue2项目流程(个人习惯)

// 1. 卸载/安装全局包
npm uninstall -g @vue/cli  /  npm install -g @vue/cli

// 2. 安装axios
npm install axios
// 2.1 基于axios封装请求响应拦截器

// 3. 安装mock
npm install mockjs
// 3.1 基于mockjs模拟未开发的接口

//4. 配置vue.config.js的代理
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000/',
        ws: true,
        changeOrigin: true,
        pathRewrite: (path) => {
          return `${path.split("/api/")[1]}`
        }
      },
      '/foo': {
        target: '<other_url>'
      }
    }
  }
}

Vue生命周期详解

44bb8198b498adb412e1af5e8dd972f.jpg

注意:

  1. 注入之后数据才具有响应式,才能被使用 created
  2. 生成真实DOM之后才能拿到DOM元素 mounted

常见应用

加载远程数据

export default {
  data(){
    return {
      news: []
    }
  },
  async created(){
    this.news = await getNews();
  }
}

直接操作DOM

export default {
  data(){
    return {
      containerWidth:0,
    	containerHeight:0
    }
  },
  mounted(){
    this.containerWidth = this.$refs.container.clientWidth;
    this.containerHeight = this.$refs.container.containerHeight;
  }
}

启动和清空计时器

export default {
  data(){
    return {
      timer: null
    }
  },
  created(){
    this.timer = setInterval(()=>{
     ... 
    }, 1000)
  },
  destroyed(){
    clearInterval(this.timer);               
  }
}

为什么Vue组件中data必须是一个函数?

对象是引用数据类型,组件复用时,如果data是一个对象,那么它们操作的是同一个数据对象,会互相影响,data是个函数的话,每次都会返回一个新的对象,互不影响。

v-if 和 v-show 有什么区别?

  • 相同点:表象上来看都是显示和隐藏元素
  • 不同点:v-if控制的是dom节点的渲不渲染,v-show控制的是css样式的切换
  • 使用:Vue的渲染效率取决于DOM树的稳定性和大小,树越稳定、渲染节点越少效率越高,故再使用v-if、v-show的时候,频繁切换的地方使用v-show,不频繁的使用v-if

computed 和 watch 的区别

计算属性computed

  • 有缓存,依赖项发生变化才会重新计算

监听属性watch

  • 没有缓存,监听的数据变了,直接触发相应操作

watch的使用

watch: {
    obj: {
      handler(newVal, oldVal){
          console.log('obj.a onchange')
      },
      immediate: true, // 组件加载立即触发
      deep: true, // 深度监听
    }
  },

immediate:组件加载立即触发回调函数执行

deep: deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj里面任何一个属性都会触发这个监听器里的 handler

优化:可以使用字符串的形式监听具体的某个属性
watch: {
    'obj.a': {
      handler(newVal, oldVal){
          console.log('obj.a onchange')
      },
      immediate: true, // 组件加载立即触发
    }
  },

vue-loader是什么?有什么作用?

vue-loader 是一个 webpack 的加载器,允许你用 Single-File Components 单文件组件的格式来写 Vue 组件。其作用就是提取 *.vue 文件中的template,script,style等,再通过 vue-template-compiler,style-loader 等插件,最终形成一个可以在浏览器中运行的 js 文件。

$nextTick

将回调延迟到下次dom更新之后运行,一般数据变化了想要获取到最新的dom可以使用this.$nextTick

vue中key的作用

  • 作用:辅助diff算法高效的更新vdom
  • diff算法比较新旧两棵树的过程:当页面数据发生变化时,Diff算法会同级比较(即比较同一层级的节点),比较原则有两点:
    1. 如果节点类型不同,直接干掉这个节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了
    2. 如果节点类型相同,则会采用就地复用策略,仅更新差异部分(节点内容、属性...),从而实现节点更新
    3. 如果有key,则会比较key和标签名,如果key和标签名相同则只移动,不会创建和删除元素
  • 经典例子:
    • 列表

      当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。

      比如一下这个情况:

      我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:

即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。

所以一句话,key的作用主要是为了高效的更新虚拟DOM。 另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。

Vue的响应式原理及双向绑定原理

响应式原理

Vue通过 Object.defineProperty 方法将对象属性转化为响应式属性,并在访问属性时收集依赖,在属性变化时通知依赖的 Watcher 对象进行更新操作,从而实现数据的响应式更新。 Vue响应式数据的原理设计思想是:数据劫持 + 观察者模式

组件通信

父子组件通信

## 父传子
父组件:<child value = '传递的数据' />
子组件:props:{
    value: {
        type: String,
        required: true,
        default: ""
    }
}
## 子传父
父组件:<child @change='change' />
子组件:this.$emit("change", "传递的数据") 

兄弟组件通信

## 事件总线
var bus = new Vue();
A: bus.$on("自定义事件名", 函数); // 注册监听事件
B: bus.$emit("自定义事件名", 数据); // 触发监听事件

新增对象属性和修改数组的某一项无法触发响应式的问题

this.$set(this.arr, 0, "123"); // 改变数组 
this.$set(this.obj, "c", "123"); // 改变对象
除此之外,Vue重写了数组的7个方法,用这七个改变原数组的方法操作数组可以触发数据响应式:
push()、pop()、shift()、unshift()、splice()、sort()、reverse()

获取组件dom

/**
 * @method 获取组件dom
 * @param {Component} comp 组件实例
 * @param {props} props 组件描述
 * @returns 
 */
function getComponentRootDom(comp, props) {
    const vm = new Vue({
        render: h => h(comp, props)
    });
    vm.$mount();
    return vm.$el;
}

// 使用:
import Icon from "@/components/Icon"
const icon = getComponentRootDom(Icon, { props: { type } })