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

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rttw6WwG-1615184295073)(https://resource.guanchao.site/ueditor/php/upload/image/20210304/1614824136410471.png#pic_center)]

3:父組件收到menu組件傳遞來的header顯示標識,再將這個顯示標識傳遞至header組件。顯示header,如下圖所示。

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

以上代碼最終執行效果:

最終代碼實現效果:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9UAKtGIe-1615184430961)(https://resource.guanchao.site/ueditor/php/upload/image/20210304/1614824208835820.gif#pic_center)]

更具體代碼實現,請參考我的代碼vue3代碼庫:https://gitee.com/camelliass/vue3blog

有好的建議,請在下方輸入你的評論。

歡迎訪問個人博客
https://guanchao.site

歡迎訪問小程序:

在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM