【每日前端面经】2024-03-16

【每日前端面经】2024-03-16

本期重点——组件通信

欢迎订阅我的前端面经专栏: 每日前端面经

Tips:

每日面经更新从 2-22 到 3-15 已有 23 篇,最近愈发觉得内容相似度高,并且理解程度不深  
于是临时停更面经,并将这些面经中的重难点以项目实战的方式展现出来供读者参阅

极简 Vue 模板:https://github.com/xxhls/vue-mini-template  
本期项目地址:https://github.com/xxhls/01-vue-component-communication

在线预览:01-vue-component-communication
在这里插入图片描述

通信方式概要

  • Props / 组件属性
  • Custom Events / 自定义属性
  • Event Bus / 事件总线
  • VueX / 状态管理
  • Provide & Inject / 依赖注入
  • Ref & Reactive
  • useAttrs
  • Pinia

逐一详解

Props / 组件属性

Props 主要用于 父组件 -> 子组件

<!-- 父组件 -->
<script setup lang="ts">
import Child01 from './01-Props/Child01.vue';
</script>

<template>
    <h1>Hello, world!</h1>

    <!-- Prop 传值 -->
    <Child01 msg="这是父组件传来的值" />
</template>
<!-- 子组件 -->
<script setup lang="ts">
defineProps<{
    msg: string
}>();
</script>

<template>
    <div>
        这是父组件传来的值 {{ msg }}
    </div>
</template>
Custom Events / 自定义事件
  1. 在子组件内使用 defineEmits 定义自定义事件
  2. 在子组件事件中通过 emit 触发自定义事件并传值
  3. 父组件通过 v-on 绑定子组件自定义事件的处理函数
  4. 在函数中可以取到子组件传来的值
<!-- 父组件 -->
<script setup lang="ts">
import Child02 from './02-Events/Child02.vue';

import { ref } from 'vue';

const value02 = ref('');
const handleEvent = (val: string) => {
    value02.value = val;
};
</script>

<template>
    <h1>Hello, world!</h1>

    <!-- Event 传值 -->
    <Child02 @myEvent="handleEvent" />
    <p>{{ value02 === '' ? '待传值' : value02 }}</p>
</template>

<!-- 子组件 -->
<script setup lang="ts">
import { defineEmits } from 'vue';

const emit = defineEmits(['myEvent']);

const handleClick = () => {
    emit('myEvent', '这是子组件传来的值');
};
</script>

<template>
    <div>
        <button @click="handleClick">点击我向父组件传值</button>
    </div>
</template>

Event Bus / 事件总线

由于 vue3 没有提供全局绑定的 $on 和 $emit,所以需要安装第三方库来实现

pnpm install mitt
// EventBus.ts
import mitt from 'mitt'
 
type Events = {
  sendMsg: string
}
 
const bus = mitt<Events>()
export default bus
<!-- 父组件 -->
<script setup lang="ts">
import Child03 from './03-EventBus/Child03.vue';
import bus from './03-EventBus/EventBus';

import { ref } from 'vue';

const value03 = ref('');
bus.on('sendMsg', (val: string) => {
    value03.value = val;
});
</script>

<template>
    <h1>Hello, world!</h1>

    03-EventBus 传值
    <Child03 />
    <p>{{ value03 === '' ? '待传值' : value03 }}</p>
</template>

<!-- 子组件 -->
<script setup lang="ts">
import bus from './EventBus';

const handleClick = () => {
    bus.emit('sendMsg', '这是子组件传来的值');
};
</script>

<template>
    <div>
        <button @click="handleClick">点击我向父组件传值</button>
    </div>
</template>
VueX / 状态管理
  1. 安装 pnpm install vuex@next
  2. 创建 VueX 仓库
  3. 挂载 VueX 仓库
  4. 父组件订阅数据
  5. 子组件发布事件
// vuex.ts
import { createStore } from 'vuex'

const VuexStore = createStore({
  state () {
    return {
      msg: 'Vuex 默认信息'
    }
  },
  mutations: {
    updateMsg (state: any, msg: string) {
      state.msg = msg
    }
  }
});

export default VuexStore;
// main.ts
import { createApp } from "vue";
import App from "./App.vue";

import VuexStore from "./04-VueX/vuex";

const app = createApp(App);

app.use(VuexStore);

app.mount("#app");
<!-- 父组件 -->
<script setup lang="ts">
import Child04 from './04-VueX/Child04.vue';

</script>

<template>
    <h1>Hello, world!</h1>

    04-VueX 传值
    <Child04 />
    <p>{{ $store.state.msg }}</p>
</template>
<!-- 子组件 -->
<script setup lang="ts">
</script>

<template>
    <div>
        <button @click="$store.commit('updateMsg', '子组件传递的值')">点击我向父组件传值</button>
    </div>
</template>
Provide & Inject / 依赖注入

在父组件通过 provide(名称, 值); 向下传递依赖
在子组件通过 const msg = inject(名称); 将依赖注入到组件内

<!-- 父组件 -->
<script setup lang="ts">
import Child05 from './05-Provide/Child05.vue';

import { provide } from 'vue';

provide('msg', '这是父组件传来的值');
</script>

<template>
    <h1>Hello, world!</h1>

    05-Provide 传值
    <Child05 />
</template>
<!-- 子组件 -->
<script setup lang="ts">
import { inject } from 'vue';

const msg = inject('msg');
</script>

<template>
    <div>
        {{ msg }}
    </div>
</template>
Ref & Reactive / 实例传递

子组件通过 expose 向外暴露数值,父组件通过 ref 获取子组件实例得到传递的值
由于父组件会在子组件挂载之前读取值,会导致 null 错误,因此采用 watch 的方式监听 ref 然后更新视图

<!-- 父组件 -->
<script setup lang="ts">
import Child06 from './06-Ref/Child06.vue';

import { ref, watch } from 'vue';

const child06Ref = ref<typeof Child06 | null>(null);
const value06 = ref('');
watch(child06Ref, (val) => {
    value06.value = val?.msg;
});
</script>

<template>
    <h1>Hello, world!</h1>

    06-Ref 传值
    <Child06 ref="child06Ref" />
    <p>{{ value06 }}</p>
</template>
<!-- 子组件 -->
<script setup lang="ts">
const msg = '这是子组件内部的值';

defineExpose({ msg });
</script>

<template>
    <div>Child06</div>
</template>
useAttrs / 属性获取

代替 props 传参,通过 useAttrs 获取全部的自定义属性

<!-- 父组件 -->
<script setup lang="ts">
import Child07 from './07-Attrs/Child07.vue';

</script>

<template>
    <h1>Hello, world!</h1>

    07-Attrs 传值
    <Child07 value07="父组件传递的值" />
</template>
<!-- 子组件 -->
<script setup lang="ts">
import { useAttrs } from 'vue';

const attrs = useAttrs();
</script>

<template>
    <div>{{ attrs.value07 }}</div>
</template>
Pinia / 状态管理
  1. 安装 pnpm install pinia
  2. 主函数挂载 pinia
  3. 创建 pinia 仓库
  4. 父组件调用仓库参数
  5. 子组件触发仓库更新函数
// main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { createPinia } from "pinia";

const app = createApp(App);

app.use(createPinia());

app.mount("#app");
// pinia.ts
import { ref } from 'vue'
import { defineStore } from 'pinia'

export const useMsgStore = defineStore('msg', () => {
    const msg = ref('Hello, Pinia!')
    function setMsg(__msg: string) {
        msg.value = __msg
    }

    return { msg, setMsg }
});
<!-- 父组件 -->
<script setup lang="ts">
import { useMsgStore } from './08-Pinia/pinia';
import Child08 from './08-Pinia/Chind08.vue';

const piniaStore = useMsgStore();
</script>

<template>
    <h1>Hello, world!</h1>

    08-Pinia 传值
    <Child08 />
    <p>{{ piniaStore.msg }}</p>
</template>
<script setup lang="ts">
import { useMsgStore } from './pinia';

const piniaStore = useMsgStore();

const handleClick = () => {
    piniaStore.setMsg('这是子组件传来的值');
};
</script>

<template>
    <div>
        <button @click="handleClick">传值</button>
    </div>
</template>
  • 32
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
《java面经-百度准入职老哥整理.pdf》是一份关于百度准入职面试的Java面经整理。这份面经是由百度准入职的老哥整理而成,其中记录了一些面试时可能会遇到的问题以及解答方法。 这份面经对于准备参加百度准入职面试的人来说非常有价值。首先,它列出了一些常见的面试问题,涵盖了Java语言的各个方面,包括基础知识、数据结构与算法、设计模式、多线程、网络编程等等。通过仔细研究和复习这些问题的答案,可以帮助面试者全面了解Java语言的特性和应用。 其次,这份面经还提供了问题的解答思路和方法,帮助面试者理清思路,正确回答问题。这对于很多面试者来说特别有帮助,因为在面试时有时会遇到一些棘手的问题,有了这份面经的指导,面试者可以更好地掌握应对策略。 不过需要注意的是,面经作为一份参考资料,不能完全依赖于它来准备面试面试官可能会问一些不在面经中列出的问题,因此考生还是需要自己对Java语言有充分的了解,并能够熟练运用。同时,面试官还会关注考生的沟通能力、解决问题的能力以及对新技术的学习和掌握能力。 总体来说,《java面经-百度准入职老哥整理.pdf》是一份非常宝贵的资料,可以帮助面试者对Java面试中可能会遇到的问题有更深入的了解,提供了解答思路和方法。但记住,面试准备还需要多方面的知识积累和实践经验的积累,才能在面试中展现自己的优势。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

糠帅傅蓝烧牛肉面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值