用 Javascript 的軟件項目
首先我們回顧一下vue2中父子組件是怎么傳值的,然后對比vue3進行詳解。
<!-- 父組件 -->
<template>
<div>
// name:父組件把值傳給子組件test-child
// childFn:子組件傳遞值給父組件的自定義方法
<test-child :name="name" @childFn="parentFn"></test-child>
子組件傳來的值 : {{message}}
</div>
</template>
<script>
export default {
data() {
return {
message: '',
name: '張三'
}
},
methods: {
// 接收子組件的傳值
parentFn(payload) {
this.message=payload;
}
}
}
</script>
<!-- 子組件 -->
<template>
<div>
{{name}}
<input type="text" v-model="message" />
<button @click="click">發送消息給父組件</button>
</div>
</template>
<script>
export default {
props:{
name:{
type:String,
default:''
}
}
data() {
return {
message: '我是來自子組件的消息'
}
},
methods: {
click() {
// 1、childFn 組件方法名,請對照父組件
// 2、message是傳遞給父組件的數據
this.$emit('childFn', this.message);
}
}
}
</script>
上面的代碼可以看到我們vue2中父子組件之間傳值是通過prop傳值給子組件,子組件通過$emit把值傳遞給父組件進行交互。那么我們下面看看vue3中是如何進行組件之間傳值的。
vue3提供了provide() 和 inject() 兩個方法,可以實現組件之間的數據傳遞。父級組件中使用 provide() 函數向子組件傳遞數據;子級組件中使用 inject() 獲取父組件傳遞過來的數據。代碼如下:
<!-- 父組件 -->
<template>
<div id="app">
<test-child></test-child>
</div>
</template>
<script>
import testChild from './components/testChild'
// 1. 按需導入 provide
import { provide } from '@vue/composition-api'
export default {
name: 'app',
setup() {
// App 根組件作為父級組件,通過 provide 函數向子級組件共享數據(不限層級)
// provide('要共享的數據名稱', 被共享的數據)
provide('color', 'red')
},
components: {
testChild
}
}
</script>
<template>
<div>
<!-- 通過屬性綁定,為標簽設置字體顏色 -->
<h3 :style="{color: themeColor}">Level One</h3>
</div>
</template>
<script>
import { inject } from '@vue/composition-api'
export default {
setup() {
// 調用 inject 函數時,通過指定的數據名稱,獲取到父級共享的數據
const themeColor=inject('color')
// 把接收到的共享數據 return 給 Template 使用,進行數據渲染
return {
themeColor
}
}
}
</script>
通過上面的代碼我們可以發現,vue3中數據傳值更加簡單了,不用再引入子組件標簽上寫屬性,直接通過provide()設置指定的名稱,可以在子組件中通過inject()拿到,是不是感覺很簡單呢。
當然了你如果非要說objecct這種就叫引用傳遞,那也是可以的。
值傳遞與引用傳遞圖例
可以這么來理解。 之前寫了手稿圖片版,現在給出文字版。
JS數據分為兩大類:
1類是原始類型primitive value,就是string,number,undefined,null,boolean加Symbol,存放在棧,可以類比為是書和玩具,
另外一類是object,叫引用類型(reference value,也有叫參考的),比如key-value對象、函數、數組等,存放在堆,可以看成是書架或箱子(盒子)。
無論那種數據類型,a=1, 或 a={},a首先是一個地址空間,它要指向1或{}這個value所在的內存地址.1是原始數據類型,存放在棧。{}因為是個盒子,除了盒子本身,里面的物件全是引用指向關系,object存在堆里。
在傳遞的時候,無輪是原始數據類型的直接量,還是引用類型Object,都是傳遞的value所在的地址,而不是這個a變量的地址。
看下面的例子:
var a=1;
var b=a;
b=2;
console.log(a, b); // 1, 2
var a={ x: 1};
var b=a;
b.x=2;
console.log(a.x, b.x); // 2, 2
// 所以,當
var a={ x: 1 };
var b=1;
var c={x: 1};
function swap(a, b, d) {
// 這是一個函數,有三個形參a,b,d
// 函數形參a,b是一個新的變量,并非外部的a和b,內部a和b指向外部a和b所指向的value地址
// 注意外部a的value本身是個盒子,傳遞進來盒子的value后,內部a與外部的a都指向這個盒子
// 當盒子里面的物件改變了時,內部的a和外部的a因為都指向這個盒子,所以里面的東西是一樣的
a={ x: 2 };
b=2;
c.x=2;
// 但是我們把內部的a,b做了新的賦值(指向更改),把內部a指向了新的一個{},把內部的b指向了新的2
// 此時內部作用域下變量a,b是新的value,a.x,b都是2, d.x因為與c.x指向相同的引用地址,因此d.x就是c.x
console.log(a.x, b, d.x); // 2, 2, 2
}
// 調用這個函數,傳入上面聲明的a,b,c變量
swap(a, b, c);
// 但在外部作用域,a與b仍然指向原來的value地址,因為傳遞是a和b的value地址,而非a和b本身的地址, c因為被函數執行時調用改變,c.x為2
console.log(a.x, b, c.x); // 1, 1, 2
點擊打開視頻講解更加詳細
【面試題】Vue路由傳參的兩種方式query和params_嗶哩嗶哩_bilibili
*請認真填寫需求信息,我們會在24小時內與您取得聯系。