用 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小时内与您取得联系。