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

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

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

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

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

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

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

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

Prpos官方文档:

https://www.vue3js.cn/docs/zh/guide/component-props.html#prop-类型

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

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

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

1.png

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

2.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: {},
};

以上代码最终执行效果:

最终代码实现效果:

3.gif

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

有好的建议,请在下方输入你的评论。

欢迎访问个人博客
https://guanchao.site

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容