VUE3(十一)自定义组件子父传值

简介: 在创建项目的时候,官方给出的页面,其实就给出了一个自定义的组件helloworld,里边包含了父传子传值,VUEX的使用,计算属性computed使用,方法的定义以及自定义组件的使用。计算属性computed和方法的定义,这里使用的并不是VUE3的新语法。在《VUE3(八)setup与ref函数》这篇中,setup的第二个参数context对象为我们提供了可触发事件emit,我们可以利用emit将子组件中的值传递给父组件。

QQ图片20220423171716.jpg

在创建项目的时候,官方给出的页面,其实就给出了一个自定义的组件helloworld,里边包含了父传子传值,VUEX的使用,计算属性computed使用,方法的定义以及自定义组件的使用。


计算属性computed和方法的定义,这里使用的并不是VUE3的新语法。


在《VUE3(八)setup与ref函数》这篇中,setup的第二个参数context对象为我们提供了可触发事件emit,我们可以利用emit将子组件中的值传递给父组件。


我这里仍旧使用上一篇中使用的项目来做测试,多说一句,使用VITE来搭建的项目其实挺好用的,就现阶段学习来说。文末会放上此次测试使用的代码仓库(码云)。


一:创建自定义组件以及使用


这个具体参照创建项目的时候给出的示例代码就好了,示例写的很清楚。


二:父组件使用prpos传递数据给子组件


Prpos官方文档:

www.vue3js.cn/docs/zh/gui…


我这里就不对语法多做解释了,说一下我的设计思路


1:首先页面加载的时候,父组件调用子组件,传递header显示标识 false


2:点击下图红框标注的按钮,子组件向父组件传递header显示标识 true


QQ图片20220423171720.png


3:父组件收到menu组件传递来的header显示标识,再将这个显示标识传递至header组件。显示header,如下图所示。


QQ图片20220423171723.png


上代码:我这里使用Menu组件来做示例

Index.vue


<template >
  <!-- 公共loading组件 -->
  <load :loading=loading />
  <div v-if="loading == false">
    <!-- 公共标题组件 -->
    <!-- VUE2.0语法,使用$refs 传值 -->
    <Header v-on:closeMenu="closeMenu" :show="showRef"  />
    <!-- <Header :show=showRef   /> -->
    <main id="main" >
      <!-- 标题加动图 -->
      <!-- banner -->
      <div class="preview" >
        <!-- 公共导航组件 -->
        <Menu v-on:showMenuByChild="showMenuByChild" :show="showRef" />
      </div>
    </main>
  </div>
</template>
<style lang="scss" scoped>
  @import "../../assets/css/pc/index.scss";
  @import "../../assets/css/pc/public.scss";
</style>
<script lang="ts">
// 引入js文件
import index from "/@/assets/js/pc/index";
// 使用js对象
export default {
  ...index,
};
</script>


Index.ts


import {
    PropType,
    ref,
    watch,
    reactive,
    toRefs,
    getCurrentInstance,
    provide,
    inject,
    onBeforeMount,// 在组件挂载之前执行的函数
    onMounted,
    onBeforeUpdate,// 在组件修改之前执行的函数
    onUpdated,
    onBeforeUnmount,// 在组件卸载之前执行的函数
    onUnmounted,
    nextTick
} from "vue";
// 引入axios钩子
import axios from "/@/hooks/axios.ts";
// 引入路由
import { useRouter, useRoute } from "vue-router";
// 引入各个自定义组件
import Header from "/@/components/pc/Header.vue";
import Menu from "/@/components/pc/Menu.vue";
// 引入公共js文件
import utils from "/@/assets/js/public/function";
// 公共状态文件
import { common } from "/@/hooks/common.ts";
export default {
    name: "index",
    components: {
        Header,
        Menu,
    },
    // VUE3 语法 第一个执行的钩子函数
    // setup官方文档 :https://www.vue3js.cn/docs/zh/guide/composition-api-setup.html#参数
    // setup(props: any, content: any) {
    setup(props: any, content: any) {
        const router = useRouter();
        const route = useRoute()
        //获取上下文实例,ctx=vue2的this
        // const { ctx,proxy } = getCurrentInstance();
        /**
         * @name: 声明data
         * @author: camellia
         * @email: guanchao_gc@qq.com
         * @date: 2021-01-10 
         */
        const data = reactive({
            // 展示header
            showRef: 0,
            // loading 是否显示
            loading: true,
        });
        // ===================================================================
        /**
         * @name: 右上角菜单
         * @author: camellia
         * @email: guanchao_gc@qq.com
         * @date: 2021-01-10 
         */
        const closeMenu = (param: number) => {
            // param就是子组件传过来的值
            data.showRef = param;
        }
/**
         * @name: menu子组件传递来的值
         * @author: camellia
         * @email: guanchao_gc@qq.com
         * @date: 2021-01-10 
         */
        const showMenuByChild = (param: number) => {
            data.showRef = param;
        }
        /**
         * @name: 将data绑定值dataRef
         * @author: camellia
         * @email: guanchao_gc@qq.com
         * @date: 2021-01-10 
         */
        const dataRef = toRefs(data);
        return {
            showMenuByChild,
            closeMenu,
            ...dataRef
        }
    },//*/
};


Menu.vue


<template>
  <div class="preview_self" style="top:0px">
      <!-- 菜单icon -->
      <nav class="navbar navbar-menu " @click="showMenu()">
        <img src="/@/assets/img/more.png"  class="img_more" />
      </nav>
  </div>
</template>
<script lang="ts">
  // 引入scss
  import "/@/assets/css/components/pc/Menu.scss";
  // 引入js文件
  import Menu from "/@/assets/js/components/pc/Menu";
  // 使用js对象
  export default {
    ...Menu,
  };
</script>


Menu.ts


import { useRouter } from "vue-router";
import {
  PropType,
  ref,
  watch,
  reactive,
  toRefs,
  inject,
  provide
} from "vue";
import { common,userinfo } from "/@/hooks/common.ts";
/**
 * @name: 定义返回的类型
 * @author: camellia
 * @email: guanchao_gc@qq.com
 * @date: 2021-01-10 15:15:53
 */
interface dataRef {
  showMenu: () => void;
  jumPage: (str: string)=>void;
  showSearch:()=>void;
  showLogin:() => void;
}
export default {
  name: "Menu",
  /**
   * @name: 父组件传递来的参数
   * @author: camellia
   * @email: guanchao_gc@qq.com
   * @date: 2021-01-10 
   */
  props: {
    show: {
      // type: Boolean as PropType<boolean>,// 布尔类型
      type: Number,// 数字类型
      default: 0, // 默认值是0
    },
  },
  // VUE3语法 setup函数
  // setup官方文档 :https://www.vue3js.cn/docs/zh/guide/composition-api-setup.html#参数
  setup(props: any, content: any): dataRef {
    const router = useRouter();
    // let menuShow = inject('menuShow')
    /**
     * @name: 声明data
     * @author: camellia
     * @email: guanchao_gc@qq.com
     * @date: 2021-01-10 
     */
    const data = reactive({
      // 菜单显示标识
      menuShow: 0,
      // 是否登录标识
      is_login:userinfo.userid ? true : false,
      // 用户头像
      figureurl:'',
      // 登录框样式
      loginstyle: { },
    });
    /**
     * @name: 监听父组件传过来的值变化
     * @author: camellia
     * @email: guanchao_gc@qq.com
     * @date: 2021-01-10 
     */
    watch(
      () => props.show,
      (show: number) => {
        data.menuShow = props.show
      }
    );
    /**
     * @name: 展示菜单
     * @author: camellia
     * @email: guanchao_gc@qq.com
     * @date: 2021-01-10 
     */
    const showMenu = () => {
      data.menuShow = 1;
      // 子组件向父组件传值
      content.emit('showMenuByChild', data.menuShow);
      // 菜单显示标识(is_menu,is_search,is_login)
      common.menuSign = 'is_menu';
    };
    /**
     * @name: 将data绑定值dataRef
     * @author: camellia
     * @email: guanchao_gc@qq.com
     * @date: 2021-01-10 
     */
    const dataRef = toRefs(data);
    return {      showMenu, 
      ...dataRef
    }
  },
  methods: {},
};


以上代码最终执行效果:


最终代码实现效果:


QQ图片20220423171726.png


更具体代码实现,请参考我的代码vue3代码库:gitee.com/camelliass/…



目录
相关文章
|
4天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
4天前
|
存储 JavaScript
Vue 组件间如何通信
Vue组件间通信是指在Vue应用中,不同组件之间传递数据和事件的方法。常用的方式有:props、自定义事件、$emit、$attrs、$refs、provide/inject、Vuex等。掌握这些方法可以实现父子组件、兄弟组件及跨级组件间的高效通信。
|
13天前
|
JavaScript 前端开发 开发者
Vue 3中的Proxy
【10月更文挑战第23天】Vue 3中的`Proxy`为响应式系统带来了更强大、更灵活的功能,解决了Vue 2中响应式系统的一些局限性,同时在性能方面也有一定的提升,为开发者提供了更好的开发体验和性能保障。
30 7
|
13天前
|
JavaScript 数据管理 Java
在 Vue 3 中使用 Proxy 实现数据双向绑定的性能如何?
【10月更文挑战第23天】Vue 3中使用Proxy实现数据双向绑定在多个方面都带来了性能的提升,从更高效的响应式追踪、更好的初始化性能、对数组操作的优化到更优的内存管理等,使得Vue 3在处理复杂的应用场景和大量数据时能够更加高效和稳定地运行。
33 1
|
13天前
|
JavaScript 开发者
在 Vue 3 中使用 Proxy 实现数据的双向绑定
【10月更文挑战第23天】Vue 3利用 `Proxy` 实现了数据的双向绑定,无论是使用内置的指令如 `v-model`,还是通过自定义事件或自定义指令,都能够方便地实现数据与视图之间的双向交互,满足不同场景下的开发需求。
34 1
|
3天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
3天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
3天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
3天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
2天前
|
JavaScript 前端开发 UED
vue学习第二章
欢迎来到我的博客!我是一名自学了2年半前端的大一学生,熟悉JavaScript与Vue,目前正在向全栈方向发展。如果你从我的博客中有所收获,欢迎关注我,我将持续更新更多优质文章。你的支持是我最大的动力!🎉🎉🎉