vue3的组件通信&v-model使用实例详解

 更新时间:2024年05月31日 10:22:10   作者:qq_42753983  
props 主要用于父组件向子组件通信,再父组件中通过使用:msg='msg'绑定需要传给子组件的属性值,然后再在子组件中用props接收该属性值,这篇文章主要介绍了vue3的组件通信&v-model使用,需要的朋友可以参考下

一、组件通信

1.props =》 父向子传值

   props 主要用于父组件向子组件通信。再父组件中通过使用:msg='msg'绑定需要传给子组件的属性值,然后再在子组件中用props接收该属性值

方法一 普通方式:
// 父组件 传值
    <child :msg1="msg1" :list="list"></child>
    <script>
       import child from "./child.vue";
       import { ref, reactive } from "vue";
       export default {
         setup() {
           //基础类型传值
           const msg1 = ref("父组件传给子组件的msg1");
           // 复杂类型(数组或对象)传值
           const list = reactive(['苹果', '梨', '香蕉'])
           return {
             msg1,
             list
           }
         }
       }
    </script>
// 子组件 接收
<template>
  <ul >
    <li  v-for="i in list" :key="i">{{ i }}</li>
  </ul>
</template>
<script>
export default {
  // props接受父组件传过来的值
  props: ["msg1", "list"],
  setup(props) {
    console.log(props);
    // { msg1:"父组件传给子组件的msg1", list:['苹果', '梨', '香蕉'] }
  },
}
</script>
方法二:使用setup语法糖
// 父组件 传值
<child :msg="msg" :list="list">
</child>
<script setup>
    import child from "./child.vue";
     const list = reactive(['苹果', '梨', '香蕉'])
    const msg = ref("父组件传给子组件的值");
</script>
// 子组件 接收
<template>
  <ul >
    <li  v-for="i in list" :key="i">{{ i }}</li>
  </ul>
</template>
<script setup>
    // 这里不需要在从vue中引入defineProps,直接用
    const props = defineProps({
        // 第一种写法
        msg: String,
        // 第二种写法
        list: {
	    	type: Array,
	   	 	default: () => [],
	  	}
    })
    console.log(props);
</script>

2.emit方式=>子向父传值defineEmits

   $emits也就是通过自定义事件传值 主要用于子组件向父组件传值

   在子组件的点击事件中 通过触发父组件中的自定义事件,把想传给父组件的信息以参数形式带过去 父组件便可拿到子组件传过来的值

// 子组件 派发
<template>
  <button @click="handleClick">按钮</button>
</template>
<script setup>
  let infos = ref('还好');
  const emit = defineEmits(['myClick']);//emits 为 defineEmits 显示声明后的对象。
// defineEmits:如存在多个监听事件则为 defineEmits(['increase','myClick'])
  const handleClick = () => {
    // 触发父组件中的方法,并把值以参数的形式传过去
    emit('myClick', infos);
    emit('increase', ref('还好33'));
  };
</script>
// 父组件 接收
<template>
    <child @myClick="onMyClick"  @increase="onIncrease"></child>
</template>
<script setup>
    import child from "./child.vue";
    // 父组件接受到子组件传过来的值
    const onMyClick = (msg) => {
        console.log(msg);
    }
    const onIncrease = (msg) => {
    console.log(msg.value);
}
</script>

3.expose / ref=》父获取子得属性或方法

expose与ref 主要用于父组件获取子组件的属性或方法。在子组件中,向外暴露出属性或方法,父组件便可以使用 ref 获取到子组件身上暴露的属性或方法。

<template>
  <div>父组件:拿到子组件的message数据:{{ msg }}</div>
  <button @click="callChildFn">调用子组件的方法</button>
  <hr />
  <Child ref="com" />
</template>
<script setup>
  import Child from './child.vue';
  const com = ref(null); // 通过 模板ref 绑定子组件
  const msg = ref('');
  onMounted(() => {
    // 在加载完成后,将子组件的 message 赋值给 msg
    msg.value = com.value.message;
  });
  function callChildFn() {
    console.log(com.value, '====');
    // 调用子组件的 changeMessage 方法
    com.value.show();
    //  重新将 子组件的message 赋值给 msg
    msg.value = com.value.message;
  }
</script>
子组件:
<template>
  <div> 子组件:</div>
</template>
<script setup>
  const message = ref('子组件传递得信息');
  const show = () => {
    console.log('子组件得方法');
  };
  defineExpose({
    message,
    show,
  });
</script>
 

4.attrs

attrs 主要用于子组件获取父组件中没有通过 props 接收的属性

<template>
  <Child :msg1="msg1" :msg2="msg2" title="子组件" />
</template>
<script setup>
  import Child from './child.vue';
  const msg1 = ref('信息1');
  const msg2 = ref('信息2');
</script>
子组件
<template>
  <div> 子组件:{{ msg1 }}-{{ attrs.msg2 }}-{{ attrs.title }}</div>
</template>
<script setup>
  // 子组件接收msg1
  defineProps({
    msg1: String,
  });
  const attrs = useAttrs();
  // 因为子组件接收了msg1,所以打印的结果中不会包含msg1, { msg2:"信息1", title: "子组件" }
  // 如果子组件没有接收msg1,打印的结果就是 { msg1: "信息1", msg2:"信息12", title: "子组件" }
  console.log(attrs);
</script>
 

5.provide/inject

遇到多层传值时,使用 props 和 emit 的方式会显得比较笨拙。这时就可以用 provide 和 inject 了。
provide与inject 主要为父组件向子组件或多级嵌套的子组件通信。
provide:在父组件中可以通过 provide 提供需要向后代组件传送的信息。
inject:从父组件到该组件无论嵌套多少层都可以直接用 inject 拿到父组件传送的信息。

<template>
  <div>------祖父组件---------</div>
  <button @click="fn">改变location的值</button>
  <br />
  <div>双向数据绑定:</div>
  姓名 {{ userInfos.username }}:
  <input v-model="userInfos.username" />
  <Child />
</template>
<script setup>
  import Child from './child.vue';
  let location = ref('传递祖父的参数');
  var userInfos = reactive({
    username: '张三',
    age: 20,
  });
  let fn = () => {
    location.value = '改变值';
  };
  provide('location', location);
  provide('userInfos', readonly(userInfos));
</script>
子组件:
<template>
	<div>
		  <Sun />
	</div>
</template>
<script>
import Sun from "./sun.vue";
</script>
孙组件:
<template>
  <div>
    <h5>-------------孙组件接受参数-------------</h5>
    <div>1.祖父组件定义provide,孙组件inject接受:{{ location }}</div>
    <p>用户信息: {{ userInfos.username }}</p>
    <br />
    <br />
    <div>2.provide inject实现父子组件传值的时候,子组件改变数据也会影响父组件</div>
    <br />姓名:
    <input v-model="userInfos.username" />
  </div>
</template>
<script setup>
  let location = inject('location');
  let userInfos = inject('userInfos');
</script>
注意:增加readonly后,子组件修改后,不会影响到父组件
类似安全的provide/inject
使用vue提供的injectionKey 类型工具来再不同的上下文中共享类型
context。ts
import { InjectionKey, Ref } from 'vue'
export interface SetUser{
 name: string
  age: number
}
// 函数的的InjectionKey
export const setUserKey: InjectionKey<SetUser> = Symbol()
父组件
<script setup>
import {setUserKey } from './context'
provide(setUserKey , { 
name: 'Karen', //如果输入1,那么类型就会报错
age: 20
 })
</script>
子组件
<script setup>
import {setUserKey } from './context'
const user =inject(setUserKey)// 输出SetUser | undefined
if(user){
console.log(user.name)//Karen
}
</script>
 

6.readonly

获取一个对象 (响应式或纯对象) 或 ref 并返回原始代理的只读代理,不能给属性重新赋值。只读代理是递归的:访问的任何嵌套 property 也是只读的。
简单得理解:要确保父组件传递得数据不会被子孙组件更改时,增加readonly

7.v-model

v-model 是 Vue 的一个语法糖。在 Vue3 中的玩法就更多了

7-1 单个v-model绑定

<template>
  <Child v-model="message" />
</template>
<script setup>
  import Child from './child.vue';
  const message = ref('父传给子');
</script>
子组件:
<template>
  <div>
    <button @click="handleClick">修改model</button>
    {{ modelValue }}
  </div>
</template>
<script setup>
  // 接收
  defineProps([
    'modelValue', // 接收父组件使用 v-model 传进来的值,必须用 modelValue 这个名字来接收
  ]);
  const emit = defineEmits(['update:modelValue']); // 必须用 update:modelValue 这个名字来通知父组件修改值
  function handleClick() {
    // 参数1:通知父组件修改值的方法名
    // 参数2:要修改的值
    emit('update:modelValue', '子改变值');
  }
</script>
 

7-2 多个v-model绑定

<template>
  <Child v-model:msg1="message1" v-model:msg2="message2" />
</template>
<script setup>
  import Child from './child.vue';
  const message1 = ref('水果1');
  const message2 = ref('水果2');
</script>
子组件:
<template>
  <div>
    <div><button @click="changeMsg1">修改msg1</button> {{ msg1 }}</div>
    <div><button @click="changeMsg2">修改msg2</button> {{ msg2 }}</div>
  </div>
</template>
<script setup>
  // 接收
  defineProps({
    msg1: String,
    msg2: String,
  });
  const emit = defineEmits(['update:msg1', 'update:msg2']);
  function changeMsg1() {
    emit('update:msg1', '蔬菜1');
  }
  function changeMsg2() {
    emit('update:msg2', '蔬菜2');
  }
</script>

7-3 v-model修饰符

v-model 还能通过 . 的方式传入修饰。v-model 有内置修饰符——.trim、.number 和 .lazy。但是,在某些情况下,你可能还需要添加自己的自定义修饰符。

<template>
  <Child v-model.uppercasefn="message" />
</template>
<script setup>
  import Child from './child.vue';
  const message = ref('水果');
</script>
子组件:
<template>
  <div>
    <div>{{ modelValue }}</div>
  </div>
</template>
<script setup>
  const props = defineProps(['modelValue', 'modelModifiers']);
  const emit = defineEmits(['update:modelValue']);
  onMounted(() => {
    console.log(props.modelModifiers, '自定义v-model 修饰符');
    // 判断有没有uppercasefn修饰符,有的话就执行 下面得方法 方法
    if (props.modelModifiers.uppercasefn) {
      emit('update:modelValue', '蔬菜');
    }
  });
</script>
 

8.插槽 slot

插槽可以理解为传一段 HTML 片段给子组件。子组件将 元素作为承载分发内容的出口。

8-1 默认插槽

插槽的基础用法非常简单,只需在 子组件 中使用 标签,就会将父组件传进来的 HTML 内容渲染出来。

<template>
  <Child>
    <div>渲染</div>
  </Child>
</template>
子组件:
// Child.vue
<template>
  <div>
    <slot></slot>
  </div>
</template>

8-2 具名插槽

具名插槽 就是在 默认插槽 的基础上进行分类,可以理解为对号入座。

父组件需要使用 标签,并在标签上使用 v-solt: + 名称 。子组件需要在 标签里用 name= 名称 对应接收。

<template>
  <Child>
    <template v-slot:monkey>
      <div>渲染</div>
    </template>
    <button>按钮</button>
  </Child>
</template>
子组件:
<template>
  <div>
    <!-- 默认插槽 -->
    <slot></slot>
    <!-- 具名插槽 -->
    <slot name="monkey"></slot>
  </div>
</template>

8-3 作用域插槽

<template>
  <!-- v-slot="{scope}" 获取子组件传上来的数据 -->
  <!-- :list="list" 把list传给子组件 -->
  <Child v-slot="{ scope }" :list="list">
    <div>
      <div>{{ scope.name }}--职业:{{ scope.occupation }}</div>
      <hr />
    </div>
  </Child>
</template>
<script setup>
  import Child from './child.vue';
  const list = reactive([
    { name: '鲁班', occupation: '辅助' },
    { name: '貂蝉', occupation: '刺客和法师' },
    { name: '虞姬', occupation: '射手' },
  ]);
</script>
子组件:
<template>
  <div>
    <!-- 用 :scope="item" 返回每一项 -->
    <slot v-for="item in list" :scope="item"></slot>
  </div>
</template>
<script setup>
  defineProps({
    list: {
      type: Array,
      default: () => [],
    },
  });
</script>
 

到此这篇关于vue3的组件通信&amp;v-model使用的文章就介绍到这了,更多相关vue3 v-model使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • ElementUi中select框在页面滚动时el-option超出元素区域的问题解决

    ElementUi中select框在页面滚动时el-option超出元素区域的问题解决

    本文主要介绍了ElementUi中select框在页面滚动时el-option超出元素区域的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-08-08
  • vue实现数字动态翻牌器

    vue实现数字动态翻牌器

    这篇文章主要为大家详细介绍了vue实现数字动态翻牌器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 解决vue路由后界面没有变化,但是链接有的问题

    解决vue路由后界面没有变化,但是链接有的问题

    今天小编就为大家分享一篇解决vue路由后界面没有变化,但是链接有的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • 解决vue前端rsa加密遇到的问题message too long for RSA

    解决vue前端rsa加密遇到的问题message too long for RS

    这篇文章主要介绍了解决vue前端rsa加密遇到的问题message too long for RSA,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Vue中.native修饰符的作用及说明

    Vue中.native修饰符的作用及说明

    这篇文章主要介绍了Vue中.native修饰符的作用及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • vue Cli 环境删除与重装教程 - 版本文档

    vue Cli 环境删除与重装教程 - 版本文档

    这篇文章主要介绍了vue Cli 环境删除与重装教程 - 版本文档,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Vue3 封装扩展并简化Vuex在组件中的调用问题

    Vue3 封装扩展并简化Vuex在组件中的调用问题

    这篇文章主要介绍了Vue3 封装扩展并简化Vuex在组件中的调用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • Vue使用NProgress的操作过程解析

    Vue使用NProgress的操作过程解析

    这篇文章主要介绍了Vue使用NProgress的操作过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • 一篇文章教会你部署vue项目到docker

    一篇文章教会你部署vue项目到docker

    在前端开发中,部署项目是我们经常发生的事情,下面这篇文章主要给大家介绍了关于部署vue项目到docker的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-04-04
  • vue中使用mockjs配置和使用方式

    vue中使用mockjs配置和使用方式

    这篇文章主要介绍了vue中使用mockjs配置和使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04

最新评论