美文网首页前端开发那些事儿
VUE3(十一)自定义组件子父传值

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

作者: camellias__ | 来源:发表于2021-03-27 14:44 被阅读0次

    在创建项目的时候,官方给出的页面,其实就给出了一个自定义的组件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

    相关文章

      网友评论

        本文标题:VUE3(十一)自定义组件子父传值

        本文链接:https://www.haomeiwen.com/subject/uchyhltx.html