在创建项目的时候,官方给出的页面,其实就给出了一个自定义的组件helloworld,里边包含了父传子传值,VUEX的使用,计算属性computed使用,方法的定义以及自定义组件的使用。
计算属性computed和方法的定义,这里使用的并不是VUE3的新语法。
在《VUE3(八)setup与ref函数》这篇中,setup的第二个参数context对象为我们提供了可触发事件emit,我们可以利用emit将子组件中的值传递给父组件。
我这里仍旧使用上一篇中使用的项目来做测试,多说一句,使用VITE来搭建的项目其实挺好用的,就现阶段学习来说。文末会放上此次测试使用的代码仓库(码云)。
一:创建自定义组件以及使用
这个具体参照创建项目的时候给出的示例代码就好了,示例写的很清楚。
二:父组件使用prpos传递数据给子组件
Prpos官方文档:
我这里就不对语法多做解释了,说一下我的设计思路
1:首先页面加载的时候,父组件调用子组件,传递header显示标识 false
2:点击下图红框标注的按钮,子组件向父组件传递header显示标识 true
3:父组件收到menu组件传递来的header显示标识,再将这个显示标识传递至header组件。显示header,如下图所示。
上代码:我这里使用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: {}, };
以上代码最终执行效果:
最终代码实现效果:
更具体代码实现,请参考我的代码vue3代码库:gitee.com/camelliass/…