上海手机网站建设价格连山区网站建设

diannao/2026/1/21 18:18:12/文章来源:
上海手机网站建设价格,连山区网站建设,北京海淀财政局网站,深圳 手机网站建设props props 的作用#xff1a;允许组件的使用者在外部传递#xff0c;实现各种各样的功能。 初始化 props 初始化 Props 主要做了 3 件事#xff1a; 设置 props 的值验证 props 合法把 props 变为响应式并且添加到组件实例 instance 上 /*** 初始化组件*/ function s…props props 的作用允许组件的使用者在外部传递实现各种各样的功能。 初始化 props 初始化 Props 主要做了 3 件事 设置 props 的值验证 props 合法把 props 变为响应式并且添加到组件实例 instance 上 /*** 初始化组件*/ function setupComponent(instance, isSSR false) {const { props, children, shapeFlag } instance.vnode// 判断是否是一个有状态的组件const isStateful shapeFlag 4// 初始化 propsinitProps(instance, props, isStateful, isSSR)// 初始化插槽initSlots(instance, children)// 设置有状态的组件实例const setupResult isStateful ? setupStatefulComponent(instance, isSSR) : undefinedreturn setupResult }/*** 初始化 Props* initProps 主要做了 3 件事* 1、设置 props 的值* 2、验证 props 合法* 3、把 props 变为响应式并且添加到组件实例 instance 上*/ function initProps(instance, rawProps, isStateful, isSSR false) {const props {}const attrs {}def(attrs, InternalObjectKey, 1)// 1、设置 props 的值setFullProps(instance, rawProps, props, attrs)// 2、验证 props 合法非生产环境下执行if ((process.env.NODE_ENV ! production)) {validateProps(props, instance.type)}// 3、把 props 变为响应式并且添加到组件实例 instance 上// 有状态组件响应式处理有状态组件是通过对象方式定义的组件if (isStateful) {instance.props isSSR ? props : shallowReactive(props)}// 函数式组件处理else {if (!instance.type.props) {instance.props attrs} else {instance.props props}}// 普通属性赋值instance.attrs attrs }设置 props 的值 /*** 设置 props 的值 - 对 props 求值然后把求得的值赋值给 props 对象和 attrs 对象中* param {Object} instance - 组件实例* param {Object} rawProps - 原始的 props 值即创建 vnode 过程中传递的 props* param {Object} props - 解析后的 props 数据* param {Object} attrs - 解析后的普通属性数据* setFullProps 主要做了 3 件事* 1、标准化 props 的配置* 2、遍历 props 数据求值* 3、对需要做转换的 props 求值*/ function setFullProps(instance, rawProps, props, attrs) {// 1、标准化 props 的配置const [options, needCastKeys] normalizePropsOptions(instance.type)// 2、遍历 props 数据求值if (rawProps) {for (const key in rawProps) {const value rawProps[key]// 一些保留的 prop 比如 ref、 key 是不会传递的if (isReservedProp(key)) continue// 连字符形式的 props 也转成驼峰形式let camelKeyif (options hasOwn(options, (camelKey camelize(key)))) {props[camelKey] value}// 非事件派发相关的且不在 props 中定义的普通属性用 attrs 保留else if (!isEmitListener(instance.type, key)) {attrs[key] value}}}// 3、对需要做转换的 props 求值if (needCastKeys) {const rawCurrentProps toRaw(props) // 需要做转换的 propsfor (let i 0; i needCastKeys.length; i) {const key needCastKeys[i]props[key] resolvePropValue(options, rawCurrentProps, key, rawCurrentProps[key])}} }标准化 props 的配置 /*** 标准化 props 的配置* description 所有形式的 props 最终都会被标准化为对象形式*/ function normalizePropsOptions(comp) {// comp.__props 用于缓存标准化的结果有缓存则直接返回if (comp.__props) {return comp.__props}const raw comp.propsconst normalized {} // 标准化后的 props 定义const needCastKeys [] // 需要转换的 props key// 处理 mixins和 extends 两个特殊的 prop因为它们的作用是扩展组件的定义所以需要对它们定义中的 props 递归执行 normalizePropsOptionslet hasExtends falseif (!shared.isFunction(comp)) {const extendProps (raw) {const [props, keys] normalizePropsOptions(raw)shared.extend(normalized, props)if (keys) {needCastKeys.push(...keys)}}if (comp.extends) {hasExtends trueextendProps(comp.extends)}if (comp.mixins) {hasExtends truecomp.mixins.forEach(extendProps)}}if (!raw !hasExtends) {return (comp._props shared.EMPTY_ARR)}// 处理数组形式的 props 定义如果 props 以数组的形式定义那么每一项一定要是一个字符串if (shared.isArray(raw)) {for (let i 0; i rawlength; i) {// 非字符串项报警告if (!shared.isString(raw[i])) {warn(/* ... */)}// 把字符串变为驼峰形式作为 key并为每一个 key 创建一个空对象作为值const normalizedKey shared.camelize(raw[i])if (validatePropName(normalizedKey)) {normalized[normalizedKey] shared.EMPTY_OBJ}}}// 处理对象形式的 props 定义else if (raw) {if (!shared.isObject(raw)) {warn(/* ... */)}for (const key in raw) {const normalizedKey shared.camelize(key)if (validatePropName(normalizedKey)) {const opt raw[key]// 标准化 prop 的定义格式const prop (normalized[normalizedKey] shared.isArray(opt) || shared.isFunction(opt) ? { type: opt } : opt)if (prop) {const booleanlndex getTypelndex(Boolean, prop.type)const stringIndex getTypelndex(String, prop.type)prop[0/* shouldCast */] booleanindex -1prop[1 /* shouldCastTrue */] stringIndex 0 || booleanlndex stringIndex//布尔类型和有默认值的 prop 都需要转换if (booleanIndex -1 || shared.hasOwn(prop, default)) {needCastKeys.push(normalizedKey)}}}}}const normalizedEntry [normalized, needCastKeys]// 缓存标准化结果comp._props normalizedEntry// 返回标准化结果return normalizedEntry }遍历 props 数据求值 // 无额外的函数对需要做转换的 props 求值 /*** 处理 Prop 的值 - 对 Props 求值然后把求得的值赋给 Props 对象的 attrs 对象中*/ function resolvePropValue(options, props, key, value) {const opt options[key]// 针对两种情况做转换if (opt ! null) {const hasDefault hasOwn(opt, default)// 默认值转换当在 prop 中定义了默认值且父组件没有传递 prop 时才取默认值if (hasDefault value undefined) {const defaultValue opt.defaultvalue opt.type ! Function isFunction(defaultValue) ? defaultValue() : defaultValue}// 布尔类型转换if (opt[0 /* shouldCast */]) {// 如果在 prop 中定义了 Boolean 类型且父组件没有传递 prop且没有定义默认值时直接转换为 falseif (!hasOwn(props, key) !hasDefault) {value false}// 其他情况转换为 trueelse if (opt[1 /* shouldCastTrue */] (value || value hyphenate(key))) {value true}}}return value }验证 props 合法 /*** 验证 props 是否合法*/ function validateProps(props, comp) {const rawValues toRaw(props)const options normalizePropsOptions(comp)[0]// 对标准化后的 props 进行遍历拿到每一个配置 opt然后执行 validateProp 验证for (const key in options) {let opt options[key]if (opt null) continuevalidateProp(key, rawValues[key], opt, !hasOwn(rawValues, key))} }/*** 验证 prop 是否合法*/ function validateProp(name, value, prop, isAbsent) {const { type, required, validator } prop// 如果配置了 required 但是没有传值则报警告if (required isAbsent) {warn(/* ... */)return}// 虽然没有值但也没有配置 required直接返回if (value null !prop.required) return// 类型检测只要满足其中一种类型就是合法的否则报警告if (type ! null type ! true) {let isValid falseconst types isArray(type) ? type : [type]const expectedTypes []}// 只要指定的类型之一匹配值就有效for (let i 0; i types.length !isValid; i) {const { valid, expectedType } assertType(value, types[i])expectedTypes.push(expectedType || )isValid valid}if (!isValid) {warn(/* ... */)return}// 如果配置了自定义校验器但是不满足校验器的规则则报警告if (validator !validator(value)) {warn(/* ... */)} }把 props 变为响应式并且添加到组件实例 instance 上 // 无额外函数问题 为什么 instance.props 要变成响应式 因为希望在子组件中监听 props 的变化而进行一些操作。 为什么用 shallowReactive API 因为 props 在更新过程中只会修改最外层属性shallowReactive 就足够了。 更新 props /*** 更新组件*/ const updateComponent (nl, n2, parentComponent, optimized) {const instance (n2.component nl.component)// 根据新旧子组件 vnode 判断是否需要更新子组件if (shouldUpdateComponent(n1, n2, parentComponent, optimized)) {instance.next n2 // 新的子组件 vnode 赋值给 instance.next// 子组件也可能因为数据变化被添加到更新队列里了移除它们防止对一个子组件重复更新 invalidateJob(instance.update)// 执行子组件的副作用渲染函数instance.update()}// 不需要更新只复制属性else {n2.component n1.componentn2.el n1.el} }/*** 更新组件 - 初始化渲染副作用*/ const setupRenderEffect (instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized) {// 创建响应式的副作用渲染函数instance.update effect(function componentEffect() {// 渲染组件if (!instance.isMounted) {// ...}// 更新组件else {let { next, vnode } instance // next 表示新的组件 vnode// 更新组件 vnode 节点信息if (next) {updateComponentPreRender(instance, next, optimized)} else {next vnode}// 渲染新的子树 vnodeconst nextTree renderComponentRoot(instance)// 缓存旧的子树 vnodeconst prevTree instance.subTree// 更新子树 vnodeinstance.subTree nextTree// 组件更新核心逻辑根据新旧子树 vnode 做 patchpatch(prevTree, nextTree,hostParentNode(prevTree.el), // 如果在 teleport 组件中父节点可能已经改变所以容器直接找旧树 DOM 元素的父节点getNextHostNode(prevTree), // 考节点在 fragment 的情况可能改变所以直接找旧树 DOM 元素的下一个节点instance, parentSuspense, isSVG)// 缓存更新后的 DOM 节点next.el nextTree.el}}, prodEffectOptions) }/*** 更新组件 - 在渲染前做一些操作*/ const updateComponentPreRender (instance, nextVNode, optimized) {nextVNode.component instanceconst prevProps instance.vnode.propsinstance.vnode nextVNodeinstance.next nullupdateProps(instance, nextVNode.props, prevProps, optimized)updateSlots(instance, nextVNode.children) }/*** 更新 Props - 把父组件渲染时求得的 props 新值更新到子组件实例的 instance.props 中*/ function updateProps(instance, rawProps, rawPrevProps, optimized) {const { props, attrs, vnode: { patchFlag } } instanceconst rawCurrentProps toRaw(props)const [options] normalizePropsOptions(instance.type)if ((optimized || patchFlag 0) !(patchFlag 16/* FULL_PROPS */)) {// 只更新动态 props 节点if (patchFlag 8/* PROPS */) {const propsToUpdate instance.vnode.dynamicPropsfor (let i 0; i propsToUpdate.length; i) {const key propsToUpdate[i]const value rawProps[key]if (options) {if (hasOwn(attrs, key)) {attrs[key] value}else {const camelizedKey camelize(key)props[camelizedKey] resolvePropValue(options, rawCurrentProps, camelizedKey, value)}} else {attrs[key] value}}}}else {// 全量 props 更新setFullProps(instance, rawProps, props, attrs)// 因为新的 props 是动态的把那些不在新的 props 中但存在于旧的 props 中的值设置为 undefinedlet kebabKeyfor (const key in rawCurrentProps) {if (!rawProps || (!hasOwn(rawProps, key) ((kebabKey hyphenate(key)) key || !hasOwn(rawProps, kebabKey)))) {if (options) {if (rawPrevProps (rawPrevProps[key] ! undefined || rawPrevProps[kebabKey] ! undefined)) {props[key] resolvePropValue(options, rawProps || EMPTY_OBJ, key, undefined)}} else {delete props[key]}}}}if ((process.env.NODE_ENV production) rawProps) {validateProps(props, instance.type)} }emit /*** 自定义事件的派发* param {Object} instance - 执行 $emit 的组件实例* param {string} event - 事件名称* param {...any} args - 事件传递的参数*/ function emit(instance, event, ...args) {const props instance.vnode.props || EMPTY_OBJ// 获取事件名称 - 把传递的 event 首字母大写然后在前面加上 onlet handlerName on${capitalize(event)}// 根据事件名称在 props 中找到对应的回调函数let handler props[handlerName]// 如果没有对应的回调函数 且 事件是以 update: 开头则尝试将事件名改为 - 形式再查找对应的回调函数if (!handler event.startsWith(update:)) {handlerName on${capitalize(hyphenate(event))}handler props[handlerName]}// 如果有对应的回调函数则执行if (handler) {callWithAsyncErrorHandling(handler, instance, 6/* COMPONENT_EVENT_HANDLER */, args)} }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/89550.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

建设银行信用卡中心网站江苏个人网站备案

https://blog.csdn.net/yinyuehepijiu/article/details/38663843

电商网站模版wordpress sora 下载

在 Java 的高并发中,对于线程并发问题的分析通常可以通过 2 个主核心进行分析 JMM 抽象内存模型和 Happens-Before 规则三大特性: 原子性, 有序性和可见性 JMM 抽象内存模型和 Happens-Before 规则, 前面我们讨论过了。这里讨论一下三大特性。 1 原子性 定义: 一个…

网站建设质量体系审核指导网站建设的域名注册

1.(Window:)cmd下输入set ORACLE_SID你想进入的数据库的那个sid(Linux:)切换到oracle用户:export ORACLE_SID你想进入的数据库的那个sid2.输入 sqlplus /nolog3.将数据库启动到RESTRICTED模式下做字符集更改:SQL> conn /as sy…

河南平台网站建设公司wordpress登录加验证码

不久前遇到一段代码使用了basename,我文件名是中文的,每次返回都只有后缀。后来发现basename函数有猫腻,不支持中文文件名,但凡有以中文开头的文件名将被忽略了。函数说明/*** 从路径中返回文件名* param string $path* 在Windows…

网站代运营做哪些淮北建筑大学

Doris 数据分布—Bucket(Tablet) 分桶的意义在于极大减少了数据的扫描范围、提高了查询的效率* 在 Doris 的存储引擎中,用户数据被水平划分为若干个数据分片(Tablet,也称作数据分桶)。每个 Tablet 包含若干数据行。各个 Tablet 之间的数据没有交集,并且在物理上是独立存…

wap手机网站源码深圳网站建设服务哪家专业

一刷~ 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符* 匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。 有几个用例超时,容我三思…

网站建设品牌排行榜域名买卖网站

目录 前言1. 问题所示2. 原理分析2.1 forward函数理解2.2 forward函数用法 前言 深入深度学习框架的代码,发现forward函数没有被显示调用 但代码确重写了forward函数,于是好奇是不是python的魔术方法作用 1. 问题所示 代码如下所示: cla…

做疏通什么网站推广好建设网站外贸

一、逻辑回归 应用场景:解决二分类问题 1、sigmoid函数 1. 公式: 2. 作用:把 (-∞,∞) 映射到 (0, 1) 3. 数学性质:单调递增函数,拐点在x0,y0.5的位置 4. 导函数公式:f…

网站开发计划书范文网站建设优化服务熊掌号

【未来的你,会感谢今天努力的你】每日两题,一难一易,每天进步一点点,可能会直接导致一场面试的成功,或工作的轻松搞定,从而升职加薪迎娶白富美,加油小伙伴! 🍅举办场地&a…

厦门外贸企业网站建设卡密网站怎么做

如果你不懂Java 并且想认真学习接触了解一下Java的语法,建议把这篇文章收藏了,多看几遍,应该可以初步掌握Java 大部分基础的语法 。 让我们出发吧!ps:本文有点长,耐心阅读 。〇,编程环境工程项目推荐使用ID…

网站开发未按合同约定开发时间完工网站有什么作用

本文为原创,如需转载,请注明作者和出处,谢谢!众所周之,在任何面向对象的语言中(包括Java、C#),在定义抽象类时必须使用abstract关键字。虽然这已经习已为常了,但实际上ab…

在虚拟机中如何做二级域名网站广州营销网站建设公司哪家好

从去年开始入坑Lisp,周周转转也算是基本入门了这一传说中的语言。Lisp确实是一门很开明的语法规范。lambda是基本定义形式,递归在其骨子深处,试图通过函数表达世界,的确这个世界是周而复始的,有些人愿意称为循环&#…

网站建设流程步骤为需求分析导入wordpress 演示数据

Spring MVC现在已经支持异步请求处理流程了一段时间&#xff0c;该支持内部利用了Tomcat / Jetty等容器的Servlet 3异步支持。 Spring Web Async支持 考虑一下需要花一点时间处理的服务呼叫&#xff0c;该服务呼叫具有延迟&#xff1a; public CompletableFuture<Message&…

个人单页网站模板2345影视下载官网电视剧

题目描述&#xff1a; 写一个宏&#xff0c;可以将一个整数的二进制位的奇数位和偶数位交换。 题目分析&#xff1a; 相信大家都可以想到位运算如&#xff1a;按位异或&#xff0c;按位取反以及<<和>>等操作符&#xff0c;可是想到这些又能怎么样&#xff1f;还是…

ks3c ks4c做网站百度应用商店app下载安装

目录 问题引入 解释 卷积 滤波 问题引入 卷积和滤波是很相似的&#xff0c;都是利用了卷积核进行操作 那么他们之间有什么区别呢&#xff1f; 卷积&#xff1a;会影响原图大小 滤波&#xff1a;不会影响原图大小 解释 卷积 我们用这样一段代码来看 import torch.nn as …

怎么建设自己淘宝网站北京专业做网站设计公司

作者&#xff1a;邹溪源&#xff0c;长沙资深互联网从业者&#xff0c;架构师社区特邀嘉宾&#xff01;一我曾经提到过最终改行从事美缝行业的老w&#xff0c;他靠自己的“不够努力”&#xff0c;最终离开了行业。但是&#xff0c;这个世界其实有点讽刺。在沉迷于安逸小日子的老…

网站形象首页flashlinux服务器wordpress

web前端何去何从&#xff1a;探索未来之路 在数字化浪潮的推动下&#xff0c;web前端技术正经历着前所未有的变革。随着新技术的不断涌现和用户体验的持续提升&#xff0c;web前端开发者们面临着前所未有的挑战与机遇。那么&#xff0c;web前端究竟何去何从&#xff1f;本文将…

带动画的网站模板东莞做网站哪家好

【多线程】线程池Future和FutureTask 【一】Future概述【1】Future的出现原因【2】Future结构图 【二】Future详解【1】Future接口源码【2】Future的5个方法【3】ThreadPoolExecutor提供了三个方法&#xff0c;来获取返回值&#xff08;1&#xff09;submit(Runnable r)&#x…

wordpress站点优化河源建网站

Backtrader 文档学习- Broker - Position 1. 概述 在backtrader中&#xff0c;Position对象是由Strategy对象创建的&#xff0c;用于跟踪策略的持仓。 通常在策略中使用以下代码检查资产的仓位&#xff1a; position&#xff08;属性&#xff09;或 getposition(dataNone, br…

阿里云虚拟主机多网站电子商务平台加盟

MongoDB分片技术 介绍 ​ 分片&#xff08;sharding&#xff09;是MongoDB用来将大型集合分割到不同服务器上采用的方法。分片这种说法起源于关系型数据库。但是实际上非关系型数据库在分片方面相比于传统的关系型数据库更有优势。 ​ 与MySQL分库方案对比&#xff0c;MongoDB…