深入了解Vue3中props的原理与使用
作者:彩虹修狗 发布时间:2024-05-09 15:09:17
前言
props指父组件往子组件中传入参数,我们来介绍下如何理解vue3的props的原理
介绍
了解其原理之前我们要清楚vue的虚拟节点是什么,有什么表现。
虚拟节点主要分成两种,分别是组件类型及元素类型,当然还有文本类型等特殊的虚拟节点。
虚拟节点都会接收三个基本参数,分别是type, props, children
对于组件类型而言:
type是一个对象里面包括基本的render函数及setup函数等
{
render() {
return h() // render函数返回一个虚拟节点
}
setup() {}
}
props是父组件往子组件传入的参数
children是父组件往子组件传入的插槽
对于元素类型而言:
type是当前节点的元素类型,如div
props是当前节点的元素属性,如class
children是当前节点的子元素是个数组,数组的内容有可能是组件也有可能是元素
原理
前提
基于此我们可以创建两个组件互为父子的组件分别是APP组件(父),FOO组件(子)
import { h } from '../h.js';
import { Foo } from './foo.js';
export const App = {
// render 页面元素内容即template
render() {
// 接收一个Foo,并通过h函数创建一个子组件node2
let node2 = h(
Foo,
{
count: 1
},
{}
)
return h(
'div',
{
id: 'root',
},
[
node2 // App接收Foo组件作为其子组件
]
);
},
setup() {
}
};
import { h } from '../h.js';
// 定义一个Foo组件用于验证Props功能
export const Foo = {
// render 页面元素内容即template
render() {
// ui 页面内容
const foo = h(
'div',
{},
'Foo' + this.count
);
return h('div', {}, [foo]);
},
// 第一个参数props,用于父子组件传值
setup(props) {
console.log(props.count); // 打印传入的props值
}
};
通过上面的代码我们可以看到,这里创建了两个文件分别代表父组件和子组件。
vue3的编译过程中我们会先去解析组件,就将组件传入patch函数中,判断当前的虚拟节点类型是组件还是元素,再走下面的编译。
上面的父组件代码中我可以看到对于Foo,我们创建了一个组件叫node2,并在props的位置中传入了一个count: 1的props。
let node2 = h(
Foo,
{
count: 1
},
{}
)
因为vue会递归的去解析每一个虚拟节点所以这个node2最后也会被解析。!!!
下面介绍解析这个node2的时候做了什么,如何实现props的功能的
创建组件实例对象
如果是组件类型的话,将我们组件的虚拟节点作为参数传入createComponentInstance, 去创建一个组件实例对象,如下:
export function createComponentInstance(vnode) {
const component = {
vnode,
type: vnode.type,
// 先创建一个空的setupState,去暂存组件类型虚拟节点的setup返回值
setupState: {},
// 创建一个props,用来存储组件虚拟节点接收的props,注意:props不允许改变 (props)
props: {},
}
return component
}
因为我们创建vnode的时候,实际上会接收接收三个基本参数,分别是type, props, children
所以这里传入的vnode会带有props字段,而这个props字段是count:1(细品)
假设我们在这一步创建了一个组件实例对象,叫instance
初始化Props操作
因为instance就接收了vnode,而组件的vnode实际上包含了props
所以接着就会执行一个initProps的操作,如果vnode中props存在,那么就将props挂载到instance下的props字段中
// 将传入的props挂载到组件实例对象上
export function initProps(instance, props) {
instance.props = props
}
这时候组件实例对象就可以正常的拿到props的值了
创建proxy对象去获取Props
因为我们知道代码中我们可以通过this. 的方式去获取props的值,而且props已经被挂载到了组件实例对象中。
因此创建一个proxy对象(后续通过bind的方式将这个对象挂载到render函数等位置,this.的时候由props去映射到对应的props中)
instance.proxy = new Proxy({ _: instance }, PublicInstanceProxyHandlers);
const PublicInstanceProxyHandlers = {
get({ _: instance }, key) {
const { setupState, props } = instance
// 如果在传入的props中,则返回的对应的值 (props)
if (hasOwn(props, key)) {
return props[key]
}
}
}
props作为参数传入setup
因为我们知道vue3中在setup中没有this,但可以接收一个props,通过这个props去获取到父组件传入的值。
那我们已经将props的值挂载到组件实例对象上,所以我们可以将props作为参数传入到setup中。
const {setup} = instance.type.setup // 获取setup函数
// 在执行setup的时候将props传入即可
setup(shallowReadonly(instance.props))
因此我们在使用的时候就可以通过接收props在setup中读值。
// 第一个参数props,用于父子组件传值
setup(props) {
console.log(props.count); // 打印传入的props值
}
将proxy挂载到render上
在解析一个虚拟节点的时候,其实会先执行setup函数,然后再执行render,因为我们可以通过this. 的方式去获取props的值。
所以我们通过bind的方式将我们之前创建proxy对象挂载到render函数中,保证其this可以正确取到props的值。
instance.render.call(instance.proxy)
来源:https://juejin.cn/post/7229625586150047800
猜你喜欢
- DesktopNexus 是我最喜爱的一个壁纸下载网站,上面有许多高质量的壁纸,几乎每天必上, 每月也必会坚持分享我这个月来收集的壁纸但是
- 前言 获得图像的关键点后,可通过计算得到关键点的描述符。关键点描述符可用于图像的特征匹配。通常,在计算图A是否包含图B的特
- 突然想到一个视频里面弹幕被和谐的一满屏的*号觉得很有趣,然后就想用python来试试写写看,结果还真玩出了点效果,思路是首先你得有一个脏话存
- system默认:managersys默认:change_on_install使用SQL Plus登录数据库时,system使用密码mana
- 最近在使用Go语言搞一个用户登录&注册的功能,说到登录&注册相关,我们油然会产生一种增加验证码的想法,因此着手实现,后来在G
- 找到给定二叉树的最小深度最小深度是从根节点到最近叶子节点的最短路径上的节点数量注意:叶子节点没有子树Example:Given binary
- 使用:foldercleanup.py -d 10 -k c:\test\keepfile.txt c:\test表示对c:\test目录只
- 目录前言cv2.drawMarker()函数说明参数说明利用鼠标回调函数交互式画点例1,简单的例子例2,删除功能总结前言这里所谓画点的意思是
- 本文实例为大家分享了Django1.11自带分页器Django的具体使用方法,供大家参考,具体内容如下接下来我编写一个 views ,名cl
- 本文将讲述vue-cli+vux-scroller实现移动端的上拉加载功能:纠错声明:网上查阅资料看到很多人都将vux和vuex弄混,在这里
- 首先,来说一下对话框: 对话框在Windows应用程序中使用非常普遍,许多应用程序的设定,与用户交互需要通过对话框来进行,因此对话框是Win
- 如何制作一个弹出式的调查窗口?执行下面这段ASP代码: <% &n
- 创建表时创建外键创建两个表格,一个名为class,create table classes(id int not null primary
- 前言相信做自动化测试的同学一定不可忽视的问题就是验证码,他几乎是一个网站登录的标配,当然,我一般是不建议在这上面浪费时间去做识别的。举个例子
- 阅读上一篇:Freshow工具使用方法一. eval加密是在网马解密中最常见的,eval在jscript脚本中实际上是一个函数,简单可以理解
- 背景在 Golang 里面,我们经常使用 channel 进行协程之间的通信。这里有一个经典的场景,也就是生产者消费者模式,生产者协程不断地
- exec sp_configure 'show advanced options',1 reconfigure exec s
- 在学习傅里叶变换的时候遇到了求周期方波信号频谱图的例子,在书上和网上查阅了一些资料,发现大都是讨论的都是下图左边的周期信号的频谱,课程老师的
- 将音频文件拷贝到程序所在目录即可。如下所示:#!/usr/bin/env python# encoding: utf-8"&quo
- 1.引言环形图(圆环)在功能上与饼图相同,整个环被分成不同的部分,用各个圆弧来表示每个数据所占的比例值。但其中心的空白可用于显示其他相关数据