前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >从 0 到 1 实现 React 系列 —— 4.setState优化和ref的实现

从 0 到 1 实现 React 系列 —— 4.setState优化和ref的实现

作者头像
牧云云
发布于 2018-08-14 09:31:52
发布于 2018-08-14 09:31:52
84500
代码可运行
举报
文章被收录于专栏:云瓣云瓣
运行总次数:0
代码可运行

看源码一个痛处是会陷进理不顺主干的困局中,本系列文章在实现一个 (x)react 的同时理顺 React 框架的主干内容(JSX/虚拟DOM/组件/生命周期/diff算法/setState/ref/...)

同步 setState 的问题

而在现有 setState 逻辑实现中,每调用一次 setState 就会执行 render 一次。因此在如下代码中,每次点击增加按钮,因为 click 方法里调用了 10 次 setState 函数,页面也会被渲染 10 次。而我们希望的是每点击一次增加按钮只执行 render 函数一次。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export default class B extends Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 0
    }
    this.click = this.click.bind(this)
  }

  click() {
    for (let i = 0; i < 10; i++) {
      this.setState({ // 在先前的逻辑中,没调用一次 setState 就会 render 一次
        count: ++this.state.count
      })
    }
  }

  render() {
    console.log(this.state.count)
    return (
      <div>
        <button onClick={this.click}>增加</button>
        <div>{this.state.count}</div>
      </div>
    )
  }
}

异步调用 setState

查阅 setState 的 api,其形式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
setState(updater, [callback])

它能接收两个参数,其中第一个参数 updater 可以为对象或者为函数 ((prevState, props) => stateChange),第二个参数为回调函数;

确定优化思路为:将多次 setState 后跟着的值进行浅合并,并借助事件循环等所有值合并好之后再进行渲染界面。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let componentArr = []

// 异步渲染
function asyncRender(updater, component, cb) {
  if (componentArr.length === 0) {
    defer(() => render())       // 利用事件循环,延迟渲染函数的调用
  }

  if (cb) defer(cb)             // 调用回调函数
  if (_.isFunction(updater)) {  // 处理 setState 后跟函数的情况
    updater = updater(component.state, component.props)
  }
  // 浅合并逻辑
  component.state = Object.assign({}, component.state, updater)
  if (componentArr.includes(component)) {
    component.state = Object.assign({}, component.state, updater)
  } else {
    componentArr.push(component)
  }
}

function render() {
  let component
  while (component = componentArr.shift()) {
    renderComponent(component) // rerender
  }
}

// 事件循环,关于 promise 的事件循环和 setTimeout 的事件循环后续会单独写篇文章。
const defer = function(fn) {
  return Promise.resolve().then(() => fn())
}

此时,每点击一次增加按钮 render 函数只执行一次了。

ref 的实现

在 react 中并不建议使用 ref 属性,而应该尽量使用状态提升,但是 react 还是提供了 ref 属性赋予了开发者操作 dom 的能力,react 的 ref 有 stringcallbackcreateRef 三种形式,分别如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// string 这种写法未来会被抛弃
class MyComponent extends Component {
  componentDidMount() {
    this.refs.myRef.focus()
  }
  render() {
    return <input ref="myRef" />
  }
}

// callback(比较通用)
class MyComponent extends Component {
  componentDidMount() {
    this.myRef.focus()
  }
  render() {
    return <input ref={(ele) => {
      this.myRef = ele
    }} />
  }
}

// react 16.3 增加,其它 react-like 框架还没有同步
class MyComponent extends Component {
  constructor() {
    super() {
      this.myRef = React.createRef()
    }
  }
  componentDidMount() {
    this.myRef.current.focus()
  }
  render() {
    return <input ref={this.myRef} />
  }
}

React ref 的前世今生 罗列了三种写法的差异,下面对上述例子中的第二种写法(比较通用)进行实现。

首先在 setAttribute 方法内补充上对 ref 的属性进行特殊处理,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function setAttribute(dom, attr, value) {
  ...
  else if (attr === 'ref') {          // 处理 ref 属性
    if (_.isFunction(value)) {
      value(dom)
    }
  }
  ...
}

针对这个例子中 this.myRef.focus() 的 focus 属性需要异步处理,因为调用 componentDidMount 的时候,界面上还未添加 dom 元素。处理 renderComponent 函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function renderComponent(component) {
  ...
  else if (component && component.componentDidMount) {
    defer(component.componentDidMount.bind(component))
  }
  ...
}

刷新页面,可以发现 input 框已为选中状态。

处理完普通元素的 ref 后,再来处理下自定义组件的 ref 的情况。之前默认自定义组件上是没属性的,现在只要针对自定义组件的 ref 属性做相应处理即可。稍微修改 vdomToDom 函数如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function vdomToDom(vdom) {
  if (_.isFunction(vdom.nodeName)) { // 此时是自定义组件
    ...
    for (const attr in vdom.attributes) { // 处理自定义组件的 ref 属性
      if (attr === 'ref' && _.isFunction(vdom.attributes[attr])) {
        vdom.attributes[attr](component)
      }
    }
    ...
  }
  ...
}

跑如下测试用例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A extends Component {
  constructor() {
    super()
    this.state = {
      count: 0
    }
    this.click = this.click.bind(this)
  }

  click() {
    this.setState({
      count: ++this.state.count
    })
  }

  render() {
    return <div>{this.state.count}</div>
  }
}

class B extends Component {
  constructor() {
    super()
    this.click = this.click.bind(this)
  }

  click() {
    this.A.click()
  }

  render() {
    return (
      <div>
        <button onClick={this.click}>1</button>
        <A ref={(e) => { this.A = e }} />
      </div>
    )
  }
}

效果如下:

项目地址关于如何 pr

本系列文章拜读和借鉴了 simple-react,在此特别感谢 Jiulong Hu 的分享。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-08-05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
ChatGPT火爆,最全prompt工程指南登GitHub热榜,标星4.7k!
---- 新智元报道   编辑:好困 Aeneas 【新智元导读】如何才能让大规模语言模型输出自己想要的结果?现在,一本超全超详提示工程指南来了,GitHub已标星4.7k。 提示工程,可以说是玩转ChatGPT、DALL·E 2等等这类AI模型的「必修课」。 但这个「提示」(prompt)具体要怎么写,多少都有些玄学在里面…… 也难怪由此诞生的新职业——提示工程师,年薪已经达到了25万-33万美元。 就在前不久,一位来自斯坦福大学的华人本科生Kevin Liu,就通过prompt injectio
新智元
2023/02/24
4390
ChatGPT火爆,最全prompt工程指南登GitHub热榜,标星4.7k!
Prompt Learning:【文心一言】提示词功能系统学习,
大型语言模型使用强化学习中的人类反馈来学习,这个过程中与人类对话的提问通常是通俗易懂的,也就是说,大型语言模型可以理解并回答一般人能听懂的问题(可以看到,后面我们所提到的技巧,用到我们日常的交流中也是可以更清晰的表达自己的目的的)。因此,即使我们不进行prompt学习,也可以使用大型语言模型来帮助我们解决问题了。但是,如果想要解决更加专业,更加复杂的问题,就需要我们学习prompt工程,以便更好的让大型语言模型来输出我们想要的结果。
汀丶人工智能
2023/04/22
1.8K0
Prompt Learning:【文心一言】提示词功能系统学习,
Prompt工程师指南从基础到进阶篇:用于开发和优化提示,以有效地使用语言模型(LMs)进行各种应用和研究主题
Prompt工程是一种相对较新的学科,用于开发和优化提示,以有效地使用语言模型(LMs)进行各种应用和研究主题。Prompt工程技能有助于更好地理解大型语言模型(LLMs)的能力和局限性。研究人员使用Prompt工程来改善LLMs在各种常见和复杂任务上的能力,
汀丶人工智能
2023/05/14
3.7K1
Prompt工程师指南从基础到进阶篇:用于开发和优化提示,以有效地使用语言模型(LMs)进行各种应用和研究主题
提示词(prompt)工程指南(三):高级提示
到此为止,已经很明显完善提示有助于在不同任务上获得更好的结果。这就是提示工程的整体理念。
云微
2023/03/31
1.7K0
Prompt提示工程上手指南:基础原理及实践(二)-Prompt主流策略
上篇文章将Prompt提示工程大体概念和具体工作流程阐述清楚了,我们知道Prompt工程是指人们向生成性人工智能(AI)服务输入提示以生成文本或图像的过程中,对这些提示进行精炼的过程。生成人工智能是一个根据人类和机器产生的数据训练的机器人,它不具备筛选你正在交流的内容以理解你实际在说什么的能力。也就是说你说的就是你得到的。那么我们使用Prompt在不进行高成本的调参,显得尤为重要,因此有很多Prompt策略适用于不同的语言大模型中,在图像大模型中Prompt策略可谓是核心必学科目了。那么本章我们将了解Prompt主流策略有什么。
fanstuck
2024/02/05
1.3K0
Prompt提示工程上手指南:基础原理及实践(二)-Prompt主流策略
Prompt Engineering:提示词工程最佳实践与应用
随着人工智能技术的不断发展,特别是大型语言模型(LLM)的兴起,提示词工程(Prompt Engineering)逐渐成为提升AI模型性能、增强任务执行效率的关键技术。Prompt Engineering通过设计和优化提示词(Prompt),引导LLM生成特定类型的输出,广泛应用于文本生成、数据增强、代码生成、问答系统等领域。本文将深入探讨Prompt Engineering的背景知识、功能点、优点、缺点,以及与市场其他技术的对比,并结合具体业务场景和底层原理,通过Java示例展示其实际应用。
小马哥学JAVA
2024/12/26
9080
Prompt提示工程上手指南:基础原理及实践(三)-Prompt个性知识库引导
Prompt系列的第二期文章已经将所有的Prompt工程主流策略讲解完毕,共涉及到六种Prompt类别模型以及具体生产内容详解。再结合系列第一篇文章具体对Prompt工程的详细介绍,也就可以达到Prompt工程师的初步入门,现在如果掌握了这些基础技能那么就可以去学习一些更高阶的Prompt技能,伴随GPT-4 Turbo达到可生成自定义的GPTs,能够搭建属于业务目标的知识数据库,我们现在需要结合知识库的种类和数据形式,去做Prompt的迭代以达到我们想要的语言生成结果。
fanstuck
2024/02/21
8600
Prompt提示工程上手指南:基础原理及实践(三)-Prompt个性知识库引导
提示词(prompt)工程指南(一):提示介绍
提示工程是一种相对较新的学科,专门用于开发和优化提示,以高效地使用语言模型(LM)来处理各种应用和研究主题。提示工程技能有助于更好地理解大型语言模型(LLMs)的能力和局限性。研究人员使用提示工程来提高LLMs在各种常见和复杂任务上的容量,例如问题解答和算术推理。开发人员使用提示工程来设计与LLMs和其他工具接口的强大而有效的提示技术。
云微
2023/03/31
2.3K0
解读提示工程(Prompt Engineering)
提示工程(Prompt Engineering),也称为上下文提示,是一种通过不更新模型的权重/参数来引导LLM行为朝着特定结果的方法。这是与AI有效交流所需结果的过程。提示工程可以用于各种任务,从回答问题到算术推理乃至各种应用领域,理解提示工程,能够帮助我们了解LLM的限制和能力。
半吊子全栈工匠
2023/10/23
9.3K0
解读提示工程(Prompt Engineering)
提升ChatGPT性能的实用指南:Prompt Engineering的艺术
提示工程是一门新兴学科,就像是为大语言模型(LLM)设计的"语言游戏"。通过这个"游戏",我们可以更有效地引导 LLM 来处理问题。只有熟悉了这个游戏的规则,我们才能更清楚地认识到 LLM 的能力和局限。
腾讯技术工程官方号
2023/08/11
1.7K0
提升ChatGPT性能的实用指南:Prompt Engineering的艺术
提示工程Prompt Engineering
上一篇大型语言模型LLM中,介绍了什么是LLM、LLM的基础内容,并提到LLM将利用词汇的分布生成文档。这一篇是关于提示和提示工程的介绍,主要内容是我们如何影响词汇的分布。
MySQLSE
2024/06/14
1380
提示工程Prompt Engineering
LLM 大模型学习必知必会系列(二):提示词工程-Prompt Engineering 以及实战闯关
prompt(提示词)是我们和 LLM 互动最常用的方式,我们提供给 LLM 的 Prompt 作为模型的输入,并希望 LLM 反馈我们期待的结果。 虽然 LLM 的功能非常强大,但 LLM 对提示词(prompt)也非常敏感。这使得提示词工程成为一项需要培养的重要技能。
汀丶人工智能
2024/05/09
3.8K0
LLM 大模型学习必知必会系列(二):提示词工程-Prompt Engineering 以及实战闯关
提示工程(prompt engineering):技术分类与提示词调优看这篇就够了
在人工智能盛起的当下,出现了一个新兴的行业——提示工程(prompt engineering)。提示词,简言之,就是我们和AI说的话。在人机交互模式下,一个好的提示词,往往能产生事半功倍的效果。文本领域,好的提示词往往能超越RAG/Agent所能发挥的能力;图片对应的视觉领域,好的提示词往往能产生更好地图片/视觉效果。
山行AI
2024/04/30
4.6K0
提示工程(prompt engineering):技术分类与提示词调优看这篇就够了
谷歌68页白皮书解密:提示工程如何重塑AI交互逻辑
谷歌发布的《提示工程白皮书》揭示了一个重要趋势:人类与AI的交互正从“指令式问答”升级为“思维协同编程” 。数据显示 ,优化后的提示设计可使LLM生成结果的准确率提升58%,代码生成效率提高120% 。
山河已无恙
2025/04/15
4680
谷歌68页白皮书解密:提示工程如何重塑AI交互逻辑
提示词(prompt)工程指南(二):基本提示
通常,学习概念的最佳方法是通过示例进行。下面我们将涵盖一些精心制作的提示示例,以执行各种有趣和不同的任务。
云微
2023/03/31
2.6K0
Prompt learning 教学[进阶篇]:简介Prompt框架并给出自然语言处理技术:Few-Shot Prompting、Self-Consistenc
看完基础篇的各种场景介绍后,你应该对 Prompt 有较深的理解。之前的章节我们讲的都是所谓的「术」,更多地集中讲如何用,但讲「道」的部分不多。高级篇除了会讲更高级的运用外,还会讲更多「道」的部分。高级篇的开篇,我们来讲一下构成 prompt 的框架。
汀丶人工智能
2023/05/12
2.3K0
99%的普通人不会用的AI沟通术:揭秘我与AI对话的沟通技巧
Prompt Engineering(提示工程)作为与 LLM 交互的关键技术,正逐渐成为连接人类需求与模型能力的桥梁。
AIGC新知
2025/04/13
1670
99%的普通人不会用的AI沟通术:揭秘我与AI对话的沟通技巧
Prompt提示工程上手指南:基础原理及实践(四)-检索增强生成(RAG)策略下的Prompt
此篇文章已经是本系列的第四篇文章,意味着我们已经进入了Prompt工程的深水区,掌握的知识和技术都在不断提高,对于Prompt的技巧策略也不能只局限于局部运用而要适应LLM大模型的整体框架去进行改进休整。较为主流的LLM模型框架设计可以基于链式思考(CoT)、思维树 (ToT)和检索增强生成 (RAG)。其中RAG框架可以算得上是AI平台研发的老生常谈之一了,因为无论是个人还是企业,都想要培养出一个属于自己领域专业的AI。但伴随而来的问题,不限于产生幻觉、缺乏对生成文本的可解释性、专业领域知识理解差,以及对最新知识的了解有限。
fanstuck
2024/02/28
2.1K3
Prompt提示工程上手指南:基础原理及实践(四)-检索增强生成(RAG)策略下的Prompt
实访用人单位:Prompt 工程师真是低门槛“香饽饽”?
15-50k 的月薪,另外还有年终奖和其他福利,你所要做的,就是研究、分析、设计在用汉语或英语做输入的情况下,更准确地描述业务想要做的事情,听起来是不是很难以置信?
深度学习与Python
2023/08/09
1.5K0
实访用人单位:Prompt 工程师真是低门槛“香饽饽”?
猫头虎分享:18种写AI 提示词 Prompt Engineering方法大集合
大家好,我是猫头虎! 今天为大家整理了 Prompt Engineering(提示工程) 的18种方法,并为每种方法提供了实际案例及对应论文参考链接。希望大家能从中受益!
猫头虎
2024/11/20
3000
猫头虎分享:18种写AI 提示词 Prompt Engineering方法大集合
推荐阅读
ChatGPT火爆,最全prompt工程指南登GitHub热榜,标星4.7k!
4390
Prompt Learning:【文心一言】提示词功能系统学习,
1.8K0
Prompt工程师指南从基础到进阶篇:用于开发和优化提示,以有效地使用语言模型(LMs)进行各种应用和研究主题
3.7K1
提示词(prompt)工程指南(三):高级提示
1.7K0
Prompt提示工程上手指南:基础原理及实践(二)-Prompt主流策略
1.3K0
Prompt Engineering:提示词工程最佳实践与应用
9080
Prompt提示工程上手指南:基础原理及实践(三)-Prompt个性知识库引导
8600
提示词(prompt)工程指南(一):提示介绍
2.3K0
解读提示工程(Prompt Engineering)
9.3K0
提升ChatGPT性能的实用指南:Prompt Engineering的艺术
1.7K0
提示工程Prompt Engineering
1380
LLM 大模型学习必知必会系列(二):提示词工程-Prompt Engineering 以及实战闯关
3.8K0
提示工程(prompt engineering):技术分类与提示词调优看这篇就够了
4.6K0
谷歌68页白皮书解密:提示工程如何重塑AI交互逻辑
4680
提示词(prompt)工程指南(二):基本提示
2.6K0
Prompt learning 教学[进阶篇]:简介Prompt框架并给出自然语言处理技术:Few-Shot Prompting、Self-Consistenc
2.3K0
99%的普通人不会用的AI沟通术:揭秘我与AI对话的沟通技巧
1670
Prompt提示工程上手指南:基础原理及实践(四)-检索增强生成(RAG)策略下的Prompt
2.1K3
实访用人单位:Prompt 工程师真是低门槛“香饽饽”?
1.5K0
猫头虎分享:18种写AI 提示词 Prompt Engineering方法大集合
3000
相关推荐
ChatGPT火爆,最全prompt工程指南登GitHub热榜,标星4.7k!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档