1 Star 0 Fork 0

boom / interview

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
vue.md 9.91 KB
一键复制 编辑 原始数据 按行查看 历史
czx 提交于 2020-06-17 18:20 . add

在使用计算属性的时,函数名和data数据源中的数据可以同名吗?

不可以,同名会报错:The computed property "xxxx" is already defined in data

因为不管是计算属性还是data还是props 都会被挂载在vm实例上,因此 这三个都不能同名


怎么给vue定义全局的方法?

  1. 挂载到Vue的prototype上。把全局方法写到一个文件里面,然后for循环挂载到Vue的prototype上,缺点是调用这个方法的时候没有提示
    Vue.prototype[key] = tools[key]
  1. 利用全局混入mixin,因为mixin里面的methods会和创建的每个单文件组件合并。这样做的优点是调用这个方法的时候有提示
new Vue({
    mixins: [mixin],
    store,
    router,
    render: h => h(App),
}).$mount('#app')
  1. 利用$root中写全局函数
// 创建全局方法
this.$root.$on('test', function(){
    console.log('test');
})

// 销毁全局方法
this.$root.$off('test');

// 调用全局方法
this.$root.$emit('test');
  1. 通过插件Vue.use
Vue.use(plugin)

兄弟组件之间进行通信

  • EventBus

EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的灾难,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。

新建 eventBus.js

import Vue from 'vue'
export default new Vue()
<!-- 父组件 -->
<template>
  <div class="home">
    <Child1 />
    <Child2 />
  </div>
</template>

A组件使用 $emit 发起事件

<template>
  <div @click="handleClick">
    Child-1
  </div>
</template>
import eventBus from '@/plugin/eventBus'
// ...
handleClick() {
  eventBus.$emit('handleClick', '兄弟组件通信')
}

B组件使用 $on 接收

<template>
  <div>
    Child-2
  </div>
</template>
import eventBus from '@/plugin/eventBus'
// ...
created() {
  eventBus.$on('handleClick', (res) => {
    console.log(res)
  })
}

以上写法要在每个组件调用 eventBus.js,我们可以在 vue 对象上绑定一个全局属性:

main.js

Vue.prototype.$eventBus = new Vue()

在组件中使用

this.$eventBus.$emit('handleClick', '兄弟组件通信')

this.$eventBus.$on('handleClick', (res) => {
  console.log(res)
})

或者,我们还可以将 eventBus 注册成插件,利用 vue.use() 进行调用:

const install = function (Vue) {
  const eventBus = new Vue({
    methods: {
      emit (event, ...args) {
        this.$emit(event, ...args)
      },
      on (event, callback) {
        this.$on(event, callback)
      },
      off (event, callback) {
        this.$off(event, callback)
      }
    }
  })
  Vue.prototype.$eventBus = eventBus
};

export default install;

main.js 中使用插件

import eventBus from './eventBus'
Vue.use(eventBus)

在组件中则可以直接使用

this.$eventBus.emit('handleClick', '兄弟组件通信')

this.$eventBus.on('handleClick', (res) => {
  console.log(res)
})

$eventBus.on 应该在 created 钩子内使用,如果在 mounted 使用,它可能接收不到其他组件来自 created 钩子内发出的事件;

使用了 $eventBus.on, 在 beforeDestroy 钩子里应该再使用 $eventBus.off 解除,因为销毁后,就没必要把监听的句柄存储在 eventBus.js 中。

beforeDestroy () {
  this.$eventBus.off('handleClick')
}
  • 使用$root也可以达到跨组件通信

组件A中,调用 $root.$emit 发起通信

eventClick() {
  this.$root.$emit('handleClick', '发起通信')
}

组件B中,调用 $root.$on 进行接收

created() {
  this.$root.$on('handleClick', res => {
    console.log(res)
  })
}

原理与 eventBus 类似


vue中通讯方式总结

  1. props
  2. $attrs / $listeners , 使用 $attrs 时,需要保证组件未使用 props 接收该属性
  3. eventBus
  4. $parent / $children , 可通过 $refs 获取指定组件
  5. $root.$emit / $root.$on , 与 eventBus 类似
  6. vuex

调用自定义组件时使用v-model

我们希望调用自定义组件时:

<ModelTest v-model="text" />

此时我们需要用 model 属性来定制 propevent

<template>
  <div>
    <!-- 允许自定义组件在使用 v-model 时定制 prop 和 event。 -->
    <input type="text" :value="text" @input="$emit('changeVal', $event.target.value)">{{text}}
  </div>
</template>

<script>
export default {
  model: {
    prop: 'text',   // 指定props中对应的字段
    event: 'changeVal'    // 事件触发时指定自定义事件
  },
  props: {
    text: {
      type: String,
      default: ''
    }
  }
}
</script>

keep-alive有关的生命周期是哪些?描述下这些生命周期

  1. activated : 页面第一次进入的时候,钩子触发的顺序是created -> mounted -> activated

  2. deactivated : 页面退出的时候会触发deactivated,当再次前进或者后退的时候只触发activated


vue中怎么重置data?

Object.assign(this.$data, this.$options.data())

e.target和e.currentTarget有什么区别?

event.currentTarget指向事件所绑定的元素,而event.target始终指向事件发生时的元素。


vue怎么实现强制刷新组件?

this.$forceUpdate()

vue给组件绑定自定义事件无效怎么解决?

1、组件外部加修饰符.navtive
2、组件内部声明$emit('自定义事件')

vue中什么是递归组件?

当前注册一个vue组件定义 name 为 'node-tree' ,在组件 template 内部调用自身,实现递归。


怎么访问到子组件的实例或者子元素?

this.$children
this.$refs.xxx

在组件中怎么访问到根实例?

this.$root

在子组件中怎么访问到父组件的实例?

this.$parent

vue组件里的定时器要怎么销毁?

const timer = setInterval(() =>{
    // 某些定时器操作
}, 500);

// 通过$once来监听定时器,在beforeDestroy钩子可以被清除。
this.$once('hook:beforeDestroy', () => {
    clearInterval(timer);
})

vue的is这个特性你有用过吗?主要用在哪些方面?

  1. 动态组件,当你多个组件需要通过 v-if 切换时,可以使用 is 来简化代码
  2. vue中is的属性引入是为了解决dom结构中对放入html的元素有限制的问题
<ul>
  <li is='my-component'></li>
</ul>

使用 scoped 后,父组件的样式将不会渗透到子组件中, 如何解决?

使用深度作用选择器 /deep/

.text-box {
  /deep/ input {
    width: 166px;
    text-align: center;
  }
}
/** 简写 **/
.a >>> .b { /* ... */ }

$nextTick

vue的DOM渲染是异步操作,当修改data时,并不会立即渲染DOM

<template>
  <div>
    <ul ref="ul">
      <li v-for="li in list" :key="li">{{li}}</li>
    </ul>
    <button @click="addItem">添加li,当前li长度{{num}}</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      num: 0,
      list: ['a']  // 默认渲染数据
    }
  },
  methods: {
    addItem() {
      this.list.push(Math.random())
      this.list.push(Math.random())
      this.list.push(Math.random())

      // // 此时获取的li长度是上一次渲染后的长度  1, 4, ...
      // const ul = this.$refs.ul
      // this.num = ul.childNodes.length

      // dom为异步渲染
      // 1. $nextTick是DOM渲染完成后的回调
      // 2. 页面渲染时会将data进行整合,多次data修改,DOM只会渲染一次
      this.$nextTick(() => {
        const ul = this.$refs.ul
        this.num = ul.childNodes.length
      })
    }
  }
}
</script>

slot插槽

vue中slot分为3种类型,插槽的概念简单来说,就是父组件向子组件插入内容

  1. 普通插槽
<!-- 子组件 -->
<div>
  <slot></slot>
</div>

<!-- 父组件 -->
<SlotTest>
  普通插槽
<SlotTest>
  1. 具名插槽
<!-- 子组件 -->
<div>
  <slot name="header"></slot>
</div>

<!-- 父组件 -->
<SlotTest>
  <template v-slot:header>
    <!-- v-slot:header 可简写 #header -->
    具名插槽
  </template>
<SlotTest>
  1. 作用域插槽

常见场景如倒计时组件,父组件传入秒数,子组件处理成时分秒返回给父组件,父组件自定义样式

<!-- 子组件 -->
<div>
  <slot :slotData="info"></slot>
</div>
data() {
  return { info: { title: "作用域插槽" } }
}

<!-- 父组件 -->
<SlotTest>
  <template v-slot="props">
    {{props.slotData}}
  </template>
<SlotTest>

动态组件

<!-- name:需要渲染的组件名 -->
<!-- 动态组件可使用keep-alive对组件状态进行缓存 -->
<component :is="name">

异步组件

使用import异步加载组件,可以使用v-if进行渲染的控制,只有在使用到该组件时才会渲染该组件

components: {
  AsyncComponent: () => import("@/components/AsyncComponent")
},

知识点汇总

  1. v-showv-if的区别

    • v-show通过display控制显示隐藏
    • v-if是渲染与销毁
    • 频繁切换时使用v-show,否则使用v-if
  2. 为何在v-for中使用key

    • 必须使用key
    • diff算法中通过tagkey来判断节点是否相同
    • 减少渲染次数,提升渲染性能
  3. 何时使用beforeDestroy?

    • 解绑自定义事件event.$off
    • 清除定时器
    • 解绑自定义DOM事件,如window scroll等
  4. Vuex中actionmutation的区别

    • action中可以处理异步,mutation不可以
    • mutation中只做原子操作(即单一功能)
    • action可以整合多个mutation
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
JavaScript
1
https://gitee.com/booboom/interview.git
git@gitee.com:booboom/interview.git
booboom
interview
interview
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891