专栏首页小码农学习笔记Vue 面试常考基础用法总结
原创

Vue 面试常考基础用法总结

基础用法要点

循环列表渲染

v-for 支持遍历数组和对象,其中 key 很重要,但不能乱写(如 random 或者 index),尽量要写和业务有关联的信息(比如 id)。

v-forv-if 不能一起使用,否则 ESLint 会报错(因为 v-for 的计算优先级更高,会生成一系列带有 v-if 属性的标签,产生重复判断)。

事件参数 event

在 Vue 中,事件参数 event 就是原生的 event 对象,没有进行任何的装饰。event.target 是事件监听的对象,即挂载到哪个元素上的;event.currentTarget 是事件被触发的地方,

用法:

  • 不传参数时,默认会传递一个 event 参数:
<template>
  <button @click="increment">按钮一</button>
</template>

<script>
export default {
  methods: {
    increment(event) {}
  }
}
</script>
  • 传递自定义参数时,如果还需要获取 event 参数,则需要手动传递 $event 参数:
<template>
  <button @click="increment(1, $event)">按钮二</button>
</template>

<script>
export default {
  methods: {
    increment(val, event) {}
  }
}
</script>

事件修饰符

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onsubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThat">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

按键修饰符

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">B</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">C</button>

表单绑定 v-model

作用范围

v-model 指令可以作用的元素为表单元素,它会元素创建了双向数据绑定:

  • input(type='text', type='radio', type='checkbox')
  • textarea
  • select

v-model 还可以用在自定义组件上,具体说明见官方文档。

使用特例

在 Vue 中,多行文本区域插值要使用 v-model 来代替:

<!-- Vue 中应该使用 v-model 来插值 -->
<textarea v-model="desc"></textarea>

<!-- Vue 中这么用是不会生效的 -->
<textarea>{{ desc }}</textarea>

修饰符 lazy number trim

<!-- 在 change 时而非 input 时更新 -->
<!-- 在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 -->
<input type="text" v-model.lazy="name">

<!-- 自动过滤用户输入的首尾空白字符 -->
<input type="text" v-model.number="name">

<!-- 自动将用户的输入值转为数值类型 -->
<input type="number" v-model.trim="age">

父子组件通信

通过 prop 实现父传子

子组件的 props 选项能够接收来自父组件数据,这是一种单向绑定,即只能父组件向子组件传递,不能反向。示例如下:

父组件 Parent.vue

<template>
  <div>
    <h1>我是父组件</h1>
    <child :message="msg"></child>
  </div>
</template>

<script>
import Child from '../components/Child.vue'

export default {
  components: { Child },
  data() {
    return {
      msg: 'hello, child'
    }
  }
}
</script>

子组件 Child.vue

<template>
  <div>
    <h1>我是子组件</h1>
    <p>父组件对我说:{{ message }}</p>
  </div>
</template>

<script>
export default {
  // 子组件通过 props 属性,接收父组件传过来的值
  props: {
    message: {
      type: String,
      default: () => {
        return ''
      }
    }
  },
}
</script>

注意事项(单向数据流)

  • 每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。
  • 不允许在子组件内部改变 prop,避免这个参数被多个子组件引用时,无法找到数据不正常的原因。
    • 如果子组件中 prop 是对象或数组,子组件对其修改后父组件相应的值也会修改(但不允许这么做);如果是字符串等基本数据类型,则会报错。
    • 如果需要将父组件传递进来的值作为一个本地数据的初始值来使用,则推荐在子组件中额外定义一个本地的 data property,并将这个 prop 用作其初始值。
    • 如果这个 prop 以一种原始的值传入且需要进行转换(例如大小写、字符串拼接等),则最好使用这个 prop 的值来定义一个计算属性

通过 $emit 实现子传父

子组件通过 $emit 触发事件给父组件发送消息,父组件通过 v-on(简写为 @) 监听子组件提交的事件。示例如下:

父组件 Parent.vue

<template>
  <div>
    <h1>我是父组件</h1>
    <child @get-message="showMsg"></child>
  </div>
</template>

<script>
import Child from '../components/Child.vue'

export default {
  components: { Child },
  methods: {
    // 参数就是子组件传递出来的数据
    showMsg(msg) {
      console.log(msg)
    }
  }
}
</script>

子组件 Child.vue

<template>
  <div>
    <h1>我是子组件</h1>
    <button @click="sendMsg">发送</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      childSay: 'hello, parent'
    }
  },
  methods: {
    // 子组件通过 emit 方法触发父组件中定义好的函数,从而将子组件中的数据传递给父组件
    sendMsg() {
      this.$emit('get-message', this.childSay)
    }
  }
}
</script>

通过 $ref 获取子组件实例

对于 ref

  • 如果 ref 用在子组件上,指向的是组件实例,可以理解为对子组件的索引,通过 $ref 可以获取到在子组件里定义的属性和方法。
  • 如果 ref 在普通的 DOM 元素上使用,引用指向的就是 DOM 元素,通过 $ref 可能获取到该 DOM 的属性集合,轻松访问到 DOM 元素,作用与 jQuery 选择器类似。

那么就好理解了,可以在父组件中通过 $ref 来直接获取子组件中的属性和方法。示例如下:

父组件 Parent.vue

<template>
  <div>
    <h1>我是父组件</h1>
    <child ref="child"></child>
  </div>
</template>

<script>
import Child from '../components/Child.vue'

export default {
  components: { Child },
  mounted() {
    console.log(this.$refs.child)
    this.$refs.child.getMessage('hello')
  }
}
</script>

子组件 Child.vue

<template>
  <div>
    <h1>我是子组件</h1>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: ''
    }
  },
  methods: {
    // 由父组件通过 $ref 引用来调用子组件的该方法
    getMessage(msg) {
      this.message = msg
    }
  }
}
</script>

对比(prop$ref 之间的区别)

  • prop 着重于数据的传递,它并不能调用子组件里的属性和方法。像创建文章组件时,自定义标题和内容这样的使用场景,最适合使用 prop
  • $ref 着重于索引,主要用来调用子组件里的属性和方法,其实并不擅长数据传递。而且 ref 用在 DOM 元素的时候,能使到选择器的作用,这个功能比作为索引更常有用到。

兄弟组件通信

项目中,我们经常会遇到兄弟组件(或隔了很多层的组件、甚至是两个不相关的组件)之间通信的情况。在大型项目中我们可以通过引入 Vuex 轻松管理各组件之间通信问题,但在一些小型的项目中,可以通过自定义事件来实现,大体思路如下:

  1. 创建一个 Vue 的实例作为媒介,让各个兄弟组件共用同一个事件机制。
  2. 数据传递方,通过一个 EventBus 事件触发 bus.$emit(方法名, 传递的数据)
  3. 数据接收方,在 mounted 中绑定监听事件,在 beforeDestroy 中解绑监听事件。

下面演示一个例子:

首先编写一个 event-bus.js,它的作用就是返回一个 Vue 的实例。

// event-bus.js
import Vue from 'vue'

export default new Vue()

组件 A 和组件 B 里面分别引入 event-bus.js 返回的 Vue 实例(此处命名为 bus)。bus 本质上就是 Vue 的实例,而 Vue 的实例本身已经实现了 $emit$on$off 这些自定义事件的能力。

在组件 A 中传递数据(触发自定义事件)。

<!-- 组件A:ComponentA.vue -->
<template>
  <div class="comment-a">
    <button @click="sendMsg">向组件B传值</button>
  </div>
</template>

<script>
import bus from './event-bus'

export default {
  data() {
    return {
      msg: ''
    }
  },
  methods: {
    sendMsg() {
      // 调用自定义事件
      bus.$emit('listenToA', this.msg)
    }
  }
}
</script>

在组件 B 中接收数据(监听自定义事件),需要做两步操作,一是绑定自定义事件,二是在 beforeDestroy 中解绑自定义事件。

<!-- 组件B:ComponentB.vue -->
<template>
  <div class="comment-b"></div>
</template>

<script>
import bus from './event-bus'

export default {
  mounted() {
    // 绑定自定义事件
    bus.$on('listenToA', this.getAData)
  },
  beforeDestroy() {
    // 及时销毁自定义事件,否则可能造成内存泄露
    bus.$off('listenToA', this.getAData)
  },
  methods: {
    getAData(val) {
      console.log(`组件 A 传递过来的数据: ${val}`)
    }
  }
}
</script>

注意事项(区别)

  • this.$emit(方法名, 传递的数据) 是调用父组件的事件。
  • bus.$emit(方法名, 传递的数据) 是调用自定义事件。

组件生命周期(单个组件)

  • 挂载阶段
    • beforeCreate => created => beforeMount => mounted
  • 更新阶段
    • beforeUpdate => updated
  • 销毁阶段
    • beforeDestroy => destroyed

在 created 阶段,把 Vue 实例初始化,存在内存中;在 mounted 阶段,组件在网页中渲染完成,此时可以做一些 Ajax 请求等操作。

在 beforeDestroy 阶段,需要解除自定义事件的绑定、销毁定时任务、解除之前定义的 window 和 document 事件等。

组件生命周期(父子组件)

1)加载渲染过程:创建 Vue 实例时从外到内,渲染时从内到外

父 beforeCreate => 父 created => 父 beforeMount => 子 beforeCreate => 子 created => 子 beforeMount => 子 mounted => 父 mounted

2)子组件更新过程

父 beforeUpdate => 子 beforeUpdate => 子 updated => 父 updated

3)父组件更新过程

父 beforeUpdate => 父 updated

4)销毁过程

父 beforeDestroy => 子 beforeDestroy => 子 destroyed => 父 destroyed


文章持续更新,本文 GitHub 前端修炼小册 已经收录,欢迎 Star。如对文章内容有不同见解,欢迎留言交流。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • hive基础总结(面试常用)

    hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务...

    用户1217611
  • Vue 面试常考高级用法特性汇总

    使用场景:在自定义的组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件。但是像单选框、复选框等类型的输入控件,它们的 ...

    文渊同学
  • 计算机网络基础常考面试题精华总结

    1、OSI,TCP/IP,五层协议的体系结构,以及各层协议 答:OSI分层 (7层):物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。 TCP/IP...

    zhisheng
  • 计算机网络基础常考面试题精华总结

    So many of our dreams at first seem impossible. Then they seem improbable.And t...

    小闫同学啊
  • JAVA基础面试总结

    1.00 什么时候使用基于接口编程? 基于接口编程、Fascade层等等抽象封装都是有开发和维护的代价的,是否使用归根结底还是要看团队人员的分工情况, 技术方...

    Java高级架构
  • Java 基础面试总结

    类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。受保护...

    黑白格
  • 面试常考知识点总结——面试必看

    答: 7层:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层 4层:应用层、传输层、网络层、链路层 为什么分层: ①多层之间相互独立,灵活性好...

    海盗船长
  • MYSQL面试常考知识点总结

    第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;

    Java帮帮
  • 面试常用排序算法总结

    其他的排序算法也经常会问到,虽然在工作中,我们很少有需要自己手写排序算法的机会,但是这种入门级的算法却是证明我们能力的一种简单方法.因此要熟悉掌握.

    呼延十
  • Java基础面试题 - 总结

    会。String类重写了hashCode方法。使用int类型h作为hash值,存在溢出截取问题。

    用户4893066
  • Java 基础面试题总结

    hey guys ,这不是也到了面试季了么,cxuan 又打算重新写一下 Java 相关的面试题,先从基础的开始吧,这些面试题属于基础系列,不包含多线程相关面试...

    cxuan
  • Java面试常考的 BIO,NIO,AIO 总结

    熟练掌握 BIO,NIO,AIO 的基本概念以及一些常见问题是你准备面试的过程中不可或缺的一部分,另外这些知识点也是你学习 Netty 的基础。

    Java技术江湖
  • HTML4+CSS2基础考试-易错点总结

    星辉
  • Nginx常见用法总结(面试必备)

    Nginx通过proxy_pass和upstream指令实现负载均衡,Nginx原生支持的负载均衡算法有如下几种:

    IT大咖说
  • 面试java基础总结大全

    JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性。

    Java团长
  • 【纯干货】Java 并发基础常见面试题总结

    进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。

    乔戈里
  • Java基础面试知识点总结

    本文主要是我最近复习Java基础原理过程中写的Java基础学习总结。Java的知识点其实非常多,并且有些知识点比较难以理解,有时候我们自以为理解了某些内容,其实...

    黄小斜学Java
  • 【Java面试总结】Java基础(上篇)

    Java虚拟机(JVM)是运行Java字节码的虚拟机。JVM 有针对不同系统的特定实现(windows,Linux,macOS),目的是使用相同的字节码,它们都...

    Rochester
  • 【Java面试总结】Java基础(下篇)

    == :它的作用 是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型 == 比较的是值,引用数据类型 == 比较的是 内存地址)

    Rochester

扫码关注云+社区

领取腾讯云代金券