【Vue3】组件通信的的各种方式和tsx风格

Vue2组件通信方式

  • props可以实现父子组件,子父组件,甚至是兄弟组件
  • 自定义事件,可以实现子父组件通信
全局事件总线bus,可以实现组件通信
  • pubsub,发布订阅模式实现任意组件通信
  • Vuex,集中式状态管理容量,可以实现任意组件通信
  • ref,父组件获取子组件实例vc
  • slot, 插槽,实现父子组件通信

Vue3组件通信方式

props
  • 需要使用到defineProps方法去接受父组件传递过来的数据
  • 页面中props可以省略前面的名字
  • props的数据是只读的
  • 父组件
<Child info="我是祖先" :money="money"></Child>
  • 子组件
<template>
  <div class="son">
       <h1>我是子组件</h1>
       <p>{{props.info}}</p>
       <p>{{props.money}}</p>
      <!--props可以省略前面的名字--->
       <p>{{info}}</p>
       <p>{{money}}</p>
       <button @click="updateProps">修改props数据</button>
  </div>
</template>

<script setup lang="ts">
//需要使用到defineProps方法去接受父组件传递过来的数据
//defineProps是Vue3提供方法,不需要引入直接使用
let props = defineProps(['info','money']); //数组|对象写法都可以
//按钮点击的回调
const updateProps = ()=>{
  // props.money+=10;  props:只读的
  console.log(props.info)
}
</script>
provide与inject依赖注入
  • 实现祖孙组件之间的通信
  • 当在深度嵌套的组件中,深层的子组件想要需要父组件的部分内容
  • 沿着prop方法传递,很麻烦
  • 采用依赖注入:
  • 祖先组件有一个provide选项来指定我们想要提供给后代组件的数据或方法
  • 子组件有一个inject来接收provide提供的数据或方法
  • 实现的效果图片
    在这里插入图片描述
  • 祖先存
    在这里插入图片描述
  • 后代取
    在这里插入图片描述

全局APi

  • 在Vue3中,不支持Vue.xxx,将它调整到应用实例app上
    在这里插入图片描述

Vue3其他改变

  • 移除keyCode作为v-on的修饰符,同时不再支持config.keycodes
  • 移除v-on.native修饰符,这个的作用就是当父组件点击子组件上的@click,不当原生click,当成了自定义事件,加了@click.native,就会变成原生click点击事件
  • 移除过滤器(filter)
组件通信之自定义事件
  • vue框架中事件分为两种,一种是原生的Dom事件,另外一种自定义事件

  • 原生dom事件可以让用户与网页进行交互,比如click这些

  • 自定义事件可以实现子组件给父组件传递数据

  • 子组件

  • 方式一

 <button @click="handler">点击我触发自定义事件xxx</button>
 //按钮点击回调
 <script setup lang="ts">
  const handler = () => {
  //第一个参数:事件类型 第二个|三个|N参数即为注入数据
    $emit('xxx','乞力马扎罗','18');
  };
 </script>
  • 方式二
<button @click="$emit('xxx','乞力马扎罗','18')">点击我触发自定义事件xxx</button>
<script setup lang="ts">
	//利用defineEmits方法返回函数触发多个自定义事件,defineEmits方法不需要引入直接使用
	let $emit = defineEmits(['xxx','click']);
</script>
  • 父组件
  <!-- 绑定自定义事件xxx:实现子组件给父组件传递数据 -->
  <Event2 @xxx="handler3" @click="handler4"></Event2>
  
  //事件回调---4
	const handler3 = (param1,param2)=>{
	    console.log(param1,param2);
	}
	//事件回调--5
	const handler4 = (param1,param2)=>{
     	console.log(param1,param2);
	}
组件通信之事件总线
  • 引入mitt插件:mitt一个方法,方法执行会返回bus对象
  • mitt方法身上带着一on方法和emit方法
  • 导入npm install – save mitt
  • impirt mitt from ‘ mitt’
    var mitt =require(‘mitt’)
  • 你也可以新建一个bus文件,创建index.ts
//引入mitt插件:mitt一个方法,方法执行会返回bus对象
import mitt from 'mitt';
const $bus = mitt();
export default $bus;
  • 子组件1
<button @click="handler">点击我给兄弟传值</button>
<script setup lang="ts">
//引入$bus对象
import $bus from '../../bus';
//点击按钮回调
const handler = ()=>{
  $bus.emit('xxx',{car:"我给你送"});
}
</script>
  • 子组件2
<script setup lang="ts">
import $bus from "../../bus";
//组合式API函数
import { onMounted } from "vue";
//组件挂载完毕的时候,当前组件绑定一个事件,接受将来兄弟组件传递的数据
onMounted(() => {
  //第一个参数:即为事件类型  第二个参数:即为事件回调
  $bus.on("xxx", (car) => {
    console.log(car);
  });
});
</script>
组件通信之v-model

父传子

  • 父组件
 <Child v-model="money"></Child>
  • 子组件
  • 接收的值modelValue是固定的
<h3>钱数:{{ modelValue }}</h3>

let props = defineProps(["modelValue"]);

子传父

  • 子组件
  • 同步更新父组件的@update事件
<button @click="handler">父子组件数据同步</button>

//方法一
//<button @click="handler" @update:modelValue=""handler>父子组件数据同步</button>

//方法2
//子组件内部按钮的点击回调
const handler = ()=>{
   //触发自定义事件
   $emit('update:modelValue',props.modelValue+1000);
}
  • 父组件
  • 自定义事件接收
let money = ref(10000);
//自定义事件的回调
const handler = (num) => {
  //将来接受子组件传递过来的数据
  money.value = num;
};

– 这样就形成闭环实现父子组件同步更新

多个v-model传值
  • 父组件
 <Child1 v-model:pageNo="pageNo" v-model:pageSize="pageSize"></Child1>
  • 子组件
<script setup lang="ts">
let props = defineProps(["name", "age"]);
let $emit = defineEmits(["update:name", "update:age"]);
//第一个按钮的事件回调
const handler = () => {
  $emit("update:name", props.name + 3);
};
</script>

TSX风格

  • 原先使用的是Template风格,现在可以扩展另一种风格TSX风格
  • 安装: npm install @vitejs/plugin-vue-jsx -D
  • 在vite.config.ts注册使用
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
//导入jsx
import vuejsx from "@vitejs/plugin-vue-jsx";
//在plugins下注册vuejsx
export default defineConfig({
  plugins: [vue(),vuejsx()],
})
使用风格一
  • 新建app.tsx
    在这里插入图片描述
  • 页面使用(接下来父级页面都是这个)
    在这里插入图片描述
使用tsx风格,使用optionsApi模式
  • defineComponent是Vue 3中高阶组件工厂函数,主要用于类型推导和提供一个统一的API,以创建Vue组件
  • 当你使用defineComponent时,它会接受一个对象或者一个包含setup函数和其他可选配置的函数,然后返回一个组件对象。这个组件对象可以直接被Vue实例化,并且会包含所有的生命周期钩子、响应式数据、计算属性、侦听器等
  • 使用变量是单括号
    在这里插入图片描述
使用tsx风格,使用setup函数模式

在这里插入图片描述

使用tsx风格,使用数组比较麻烦
  • v-if 也不支持,需要用三元表达式
    在这里插入图片描述
使用tsx风格,来父子组件传值
  • 子组件,的tsx风格
import { defineComponent } from 'vue';
//ref的值,在template中自动解包,在tsx不会,得使用.value
export default defineComponent({
  props: {
    name: String,
  },
  emits: ['on-getfdetail'],
  setup(props, { emit }) {
    const list = [{ name: '花花1' }, { name: '花花2' }, { name: '花花3' }];
    const fun = (item) => {
      console.log('回传', item);
      emit('on-getfdetail', item);
    };
    return () => (
      <>
        <div>props:{props?.name}</div>
        <hr />
        {list.map((v) => {
          //有问题,一上来就直接调用了
          // return <div onClick={fun()}>{v.name}</div>;
          // 函数柯里化解决
          return <div onClick={() => fun(v)}>{v.name}</div>;
        })}
      </>
    );
  },
});

  • App.vue页面父组件
<template>
  <div>
    <tsx @on-getfdetail="getname" name="乞力马扎罗"></tsx>
  </div>
</template>
<script setup lang="ts">
import tsx from './App';
const getname = (item) => {
  console.log(item, '子组件传的值');
};
</script>

<style scoped></style>

在这里插入图片描述

使用tsx风格,插槽
import { defineComponent } from 'vue';
//ref的值,在template中自动解包,在tsx不会,得使用.value

//留下插槽位置
const A = (_, { slots }) => (
  <>
    <div>{slots.default ? slots.default() : '默认值'}</div>
    <div>{slots.foo?.()}</div>
  </>
);
export default defineComponent({
  setup() {
    //定义插槽要展示的内容
    const slotName = {
      default: () => (<div>展示默认插槽</div>),
      foo: () => (<div>插槽</div>)
    };
    return () => (
      <>
        {/* 父组件展示内容 */}
        <A v-slots={slotName}></A>
      </>
    );
  },
});
  • 效果展示
    在这里插入图片描述
  • 13
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值