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() {
//基礎(chǔ)類型傳值
const msg1 = ref("父組件傳給子組件的msg1");
// 復(fù)雜類型(數(shù)組或?qū)ο螅﹤髦?
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也就是通過自定義事件傳值 主要用于子組件向父組件傳值
在子組件的點擊事件中 通過觸發(fā)父組件中的自定義事件,把想傳給父組件的信息以參數(shù)形式帶過去 父組件便可拿到子組件傳過來的值
// 子組件 派發(fā)
<template>
<button @click="handleClick">按鈕</button>
</template>
<script setup>
let infos = ref('還好');
const emit = defineEmits(['myClick']);//emits 為 defineEmits 顯示聲明后的對象。
// defineEmits:如存在多個監(jiān)聽事件則為 defineEmits(['increase','myClick'])
const handleClick = () => {
// 觸發(fā)父組件中的方法,并把值以參數(shù)的形式傳過去
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數(shù)據(jù):{{ msg }}</div>
<button @click="callChildFn">調(diào)用子組件的方法</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, '====');
// 調(diào)用子組件的 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,所以打印的結(jié)果中不會包含msg1, { msg2:"信息1", title: "子組件" }
// 如果子組件沒有接收msg1,打印的結(jié)果就是 { 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>雙向數(shù)據(jù)綁定:</div>
姓名 {{ userInfos.username }}:
<input v-model="userInfos.username" />
<Child />
</template>
<script setup>
import Child from './child.vue';
let location = ref('傳遞祖父的參數(shù)');
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>-------------孫組件接受參數(shù)-------------</h5>
<div>1.祖父組件定義provide,孫組件inject接受:{{ location }}</div>
<p>用戶信息: {{ userInfos.username }}</p>
<br />
<br />
<div>2.provide inject實現(xiàn)父子組件傳值的時候,子組件改變數(shù)據(jù)也會影響父組件</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
}
// 函數(shù)的的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
獲取一個對象 (響應(yīng)式或純對象) 或 ref 并返回原始代理的只讀代理,不能給屬性重新賦值。只讀代理是遞歸的:訪問的任何嵌套 property 也是只讀的。
簡單得理解:要確保父組件傳遞得數(shù)據(jù)不會被子孫組件更改時,增加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 傳進(jìn)來的值,必須用 modelValue 這個名字來接收
]);
const emit = defineEmits(['update:modelValue']); // 必須用 update:modelValue 這個名字來通知父組件修改值
function handleClick() {
// 參數(shù)1:通知父組件修改值的方法名
// 參數(shù)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 有內(nèi)置修飾符——.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修飾符,有的話就執(zhí)行 下面得方法 方法
if (props.modelModifiers.uppercasefn) {
emit('update:modelValue', '蔬菜');
}
});
</script>
8.插槽 slot
插槽可以理解為傳一段 HTML 片段給子組件。子組件將 元素作為承載分發(fā)內(nèi)容的出口。
8-1 默認(rèn)插槽
插槽的基礎(chǔ)用法非常簡單,只需在 子組件 中使用 標(biāo)簽,就會將父組件傳進(jìn)來的 HTML 內(nèi)容渲染出來。
<template>
<Child>
<div>渲染</div>
</Child>
</template>
子組件:
// Child.vue
<template>
<div>
<slot></slot>
</div>
</template>8-2 具名插槽
具名插槽 就是在 默認(rèn)插槽 的基礎(chǔ)上進(jìn)行分類,可以理解為對號入座。
父組件需要使用 標(biāo)簽,并在標(biāo)簽上使用 v-solt: + 名稱 。子組件需要在 標(biāo)簽里用 name= 名稱 對應(yīng)接收。
<template>
<Child>
<template v-slot:monkey>
<div>渲染</div>
</template>
<button>按鈕</button>
</Child>
</template>
子組件:
<template>
<div>
<!-- 默認(rèn)插槽 -->
<slot></slot>
<!-- 具名插槽 -->
<slot name="monkey"></slot>
</div>
</template>8-3 作用域插槽
<template>
<!-- v-slot="{scope}" 獲取子組件傳上來的數(shù)據(jù) -->
<!-- :list="list" 把list傳給子組件 -->
<Child v-slot="{ scope }" :list="list">
<div>
<div>{{ scope.name }}--職業(yè):{{ 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>
到此這篇關(guān)于vue3的組件通信&v-model使用的文章就介紹到這了,更多相關(guān)vue3 v-model使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- vue 2 實現(xiàn)自定義組件一到多個v-model雙向數(shù)據(jù)綁定的方法(最新推薦)
- vue3?中v-model語法糖示例詳解
- Vue3?使用v-model實現(xiàn)父子組件通信的方法(常用在組件封裝規(guī)范中)
- Vue3.4中v-model雙向數(shù)據(jù)綁定新玩法詳解
- vue3利用v-model實現(xiàn)父子組件之間數(shù)據(jù)同步的代碼詳解
- Vue3中v-model語法糖的三種寫法詳解
- vue3+Element?Plus?v-model實現(xiàn)父子組件數(shù)據(jù)同步的案例代碼
- vue3組件的v-model:value與v-model的區(qū)別解析
相關(guān)文章
vue使用Google Recaptcha驗證的實現(xiàn)示例
我們最近的項目中需要使用谷歌機器人驗證,所以就動手實現(xiàn)一下,本文就來詳細(xì)的介紹一下vue Google Recaptcha驗證,感興趣的可以了解一下2021-08-08
vue.js單頁面應(yīng)用實例的簡單實現(xiàn)
本篇文章主要介紹了vue.js單頁面應(yīng)用實例的簡單實現(xiàn),使用單頁應(yīng)用,沒有頁面切換,就沒有白屏阻塞,可以大大提高 H5 的性能,達(dá)到接近原生的流暢體驗。2017-04-04
vue?element?el-select下拉滾動加載的方法
很多朋友都遇到這樣一個問題在使用vue+element的el-select下拉框加載返回數(shù)據(jù)太多時,會造成卡頓,用戶體驗欠佳,這篇文章主要介紹了vue?element?el-select下拉滾動加載方法,需要的朋友可以參考下2022-11-11
使用element+vuedraggable實現(xiàn)圖片上傳拖拽排序
這篇文章主要為大家詳細(xì)介紹了使用element+vuedraggable實現(xiàn)圖片上傳拖拽排序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04
關(guān)于antd中select搜索框改變搜索值的問題
這篇文章主要介紹了關(guān)于antd中select搜索框改變搜索值的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04

