wolichuang / dailyInterview

面试、工作中遇到的issue
0 stars 0 forks source link

vue 基础知识 #45

Open wolichuang opened 3 years ago

wolichuang commented 3 years ago

Vue.nextTick()

在修改数据之后立即使用这个方法,获取更新后的 DOM。所以放在Vue.nextTick()回调函数中的执行的应该是会对DOM进行操作的

1. 如果需要 在 created()函数进行的DOM操作,一定要放在Vue.nextTick()的回调函数中。
原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载已完成。

2. 当数据双向绑定改变 dom元素后,对新DOM进行操作的方法应该放在 nextTick  中。

3. Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 当中观察到数据变化的 watcher 推送进这个队列。如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和Dom操作。而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。
当你设置 vm.someData = 'new value',DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的DOM更新。如果此时你想要根据更新的 DOM 状态去做某些事情,就会出现问题。
为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。

Vue子组件调用父组件的方法

1. 第一种方法是直接在子组件中通过this.$parent.event来调用父组件的方法

<template>
  <div>
    <child></child>
  </div>
</template>
<script>
  import child from '~/components/dam/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('测试');
      }
    }
  };
</script>

<template>
  <div>
    <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default {
    methods: {
      childMethod() {
        this.$parent.fatherMethod();
      }
    }
  };
</script>

2. 第二种方法是在子组件里用$emit向父组件触发一个事件,父组件监听这个事件。

<template>
  <div>
    <child @fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from '~/components/dam/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('测试');
      }
    }
  };
</script>

<template>
  <div>
    <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default {
    methods: {
      childMethod() {
        this.$emit('fatherMethod');
      }
    }
  };
</script>

3. 第三种是父组件把方法传入子组件中,在子组件里直接调用这个方法

<template>
  <div>
    <child :fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from '~/components/dam/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('测试');
      }
    }
  };
</script>

<template>
  <div>
    <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default {
    props: {
      fatherMethod: {
        type: Function,
        default: null
      }
    },
    methods: {
      childMethod() {
        if (this.fatherMethod) {
          this.fatherMethod();
        }
      }
    }
  };
</script>

vue 监听路由变化

watch: {
    $route: 'loadPath' // 监听事件
  },
  loadPath() {
      this.listParams.title = this.$route.query.input;
      this.fetchData(); // 加载数据
    },
watch:{
   fristName:{
       handle(newValue,oldValue){
         this.fullValue = newValue + this.lastName;
      },
      immediate: true //表示声明了fistName后,立即执行handle方法
      deep: true  // 加上deep:true后,就可以监听obj属性的变化了
   }
}

// 开销较大可以直接监听对象属性名
// 直接监听对象的属性
watch:{
   obj.a:{
      handle(newValue, oldValue){
         console.log('obj.a is changed')
      },
      immediate: true,
      // deep: true  
   }
}

vue 下载

downExcel(){
      var link = document.createElement("a"); 
      link.setAttribute("download", "");
      link.href = `${process.env.BASE_URL}file/beian_import.xls`;
      link.click();
      link.remove();
    },
wolichuang commented 3 years ago

刷新页面 store状态

1、hash 路由模式

使用 window.location.href 和 this.$router.push 或 replace
不管使用这三种方式的哪一种 store 都不会丢

2、history路由

this.router.replace store 不丢
window.location.href 页面刷新 store 丢

总结: 只有路由模式是history 且用location.href跳转路由的时候 store会丢

computed 使用

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})

多组件引用

// export { default as ScreenDialog } from './screen-dialog.vue';
const path = require('path');
const files = require.context('@/components/ControlMeeting', false, /\.vue$/);
const modules = {};
files.keys().forEach((key) => {
  const name = path.basename(key, '.vue');
  modules[name] = files(key).default || files(key);
});
export default {
  components: modules
};

import * as modules from '@/components/ControlMeeting/index.js';
const {
  CountDown,
  CreateLivingDialog,
  EndTimeDialog,
  ScreenDialog,
  SubTitleDialog
} = modules.default.components;