Web3学习笔记(八)React基础07

最后一章节了,终于坚持下来把官方文档看完了,接下来就是实战了,才能理解的更深刻。

  • 响应式值应该重新进行同步Effect,因为它们可以随着时间的推移而发生变化。
  • 组件内部的所有值(包括props、state和组件体内的变量)都是响应式的。任何响应式值都可以在重新渲染时发生变化,所以需要将响应式值包括在Effect的依赖项中。
  • 我们不能“选择”依赖项。依赖项必须包括Effect中读取的每个响应式值。代码检查工具会强制执行此规则。
  • 我们可以将非响应式逻辑从Effect移到Effect Event中。
  • Effect Event的局限性:只在Effect内部调用他们,永远不要把他们传给其他的组件或者Hook。
  • 如果想读取最新值而不“反应”它,请从Effect中提取出一个Effect Event。
  • 在JavaScript中,如果对象和函数是在不同时间创建的,则它们被认为是不同的。
  • React组件名称必须以大写字母开头,比如StatusBar和SaveButton。React组件还需要返回一些React能够显示的内容,比如一段JSX。
  • Hook的名称必须以use开头,然后紧跟一个大写字母,就像内置的useState。Hook可以返回任意值。
  • 每次组件重新渲染时,所有的Hook会重新运行。

Web3学习笔记(七)React基础06

最后这段理解起来不是那么容易,不管怎样,先记录下来重点:

  • Effect通常用于暂时“跳出”React,并与一些外部系统进行同步。这包括浏览器 API、第三方小部件,以及网络等等。
  • 默认情况下,Effect在每次渲染(包括初始渲染)后运行。
  • 通过在调用useEffect时指定一个依赖数组作为第二个参数,可以让 React跳过不必要地重新运行Effect。
  • 依赖数组可以包含多个依赖项。只有当指定的所有依赖项的值都与上一次渲染时完全相同,React才会跳过重新运行该 Effect。
  • 我们不能“选择”依赖项,它们是由 Effect 内部的代码所决定的。
  • 没有依赖数组时,useEffect中代码会在每次渲染后运行;
  • 依赖数组为空数组为空时,useEffect中代码只会在组件挂载(首次出现)时运行;
  • 依赖数组有依赖项时,useEffect中代码不但会在组件挂载时运行,而且当任一依赖项的值自上次渲染后发生变化后也会运行。
  • 如果你可以在渲染期间计算某些内容,则不需要使用 Effect。
  • 如果一个值可以基于现有的props或state计算得出,不要把它作为一个state,而是在渲染期间直接计算这个值。
  • 组件显示时就需要执行的代码应该放在Effect中,否则应该放在事件处理函数中。

这是最后章节了,虽然理解有些困难,但是结合示例代码,还是能理解,只不过不容易记住而已。

Web3学习笔记(六)React基础05

学到最后章节,刚接触了ref,我们来看下有哪些重点内容吧。

  • Refs是一种脱围机制。我们应该只在必须“跳出React”时使用它们。这方面的常见示例包括管理焦点、滚动位置或调用React未暴露的浏览器API。
  • 当我们希望组件“记住”某些信息,但又不想让这些信息触发新的渲染时,我们可以使用ref
  • 与state一样,ref在重新渲染之间由React保留。但是,设置state会重新渲染组件,而更改ref不会!
  • 我们可以通过ref.current属性访问该ref的当前值。
  • 可以使用ref来存储timeout ID、DOM元素和其他不影响组件渲染输出的对象。
  • 我们通过传递<div ref={myRef}>指示React将DOM节点放入myRef.current。
  • 不要在渲染过程中读取或写入ref.current。这会使我们的组件难以预测。

Come On!

Web3学习笔记(五)React基础04

学到状态管理了,学习如何组织好状态,如何保持状态更新逻辑的可维护性,怎么样跨组件共享状态。

  • 在React中,我们不必直接去操作UI,比如不必直接启用、关闭、显示或隐藏组件。相反,我们只需要声明你想要显示的内容,React就会通过计算得出该如何去更新UI。
  • 写出你的组件中所有的视图状态。确定是什么触发了这些state的改变。通过useState模块化内存中的state。
  • 构建state的原则:合并关联的state、避免互相矛盾的state、避免冗余的state、避免重复的state、避免深度嵌套的state。
  • 不要在state中镜像props,只有当我们想要忽略特定props属性的所有更新时,将props“镜像”到state才有意义。按照惯例,prop名称以initial或default开头,以阐明该prop的新值将被忽略。
  • 如果两个state变量总是一起更新,请考虑将它们合并为一个。如果深度嵌套state更新很复杂,请尝试将其展开扁平化。
  • 有时候,我们希望两个组件的状态始终同步更改。要实现这一点,可以将相关state从这两个组件上移除,并把state放到它们的公共父级,再通过props将state传递给这两个组件。这被称为“状态提升”
  • 组件“受控”(由prop驱动)或是“不受控”(由state驱动)
  • 如果你想在重新渲染时保留state,几次渲染中的树形结构就应该相互“匹配”。结构不同就会导致state的销毁,因为React会在将一个组件从树中移除时销毁它的state。
  • 只要在相同位置渲染的是相同组件,React就会保留状态。你可以通过为一个子树指定一个不同的key来重置它的state。

Web3学习笔记(四)React基础03

到添加交互的环节了,教会我怎么样添加事件和设置state,以及state和页面渲染的关系,需要真正理解下面的摘抄:

  • 事件处理函数通常在组件内部定义,名称一般以handle开头,后跟事件名称。
  • 必须传递事件处理函数,而非函数调用!onClick={handleClick},不是onClick={handleClick()}。
  • 可以在父组件中定义一个事件处理函数,并将其作为prop传递给子组件。
  • 事件会向上传播。通过事件的第一个参数调用e.stopPropagation()来防止这种情况。
  • 当一个组件需要在多次渲染间“记住”某些信息时使用state变量,State变量是通过调用useState Hook来声明的。
  • Hook可能会让我们想起import:它们需要在非条件语句中调用。调用Hook时,包括useState,仅在组件或另一个Hook的顶层被调用才有效。
  • state完全私有于声明它的组件。父组件无法更改它。这使你可以向任何组件添加或删除state,而不会影响其他组件。
  • State是组件私有的。如果你在两个地方渲染它,则每个副本都有独属于自己的state。
  • 一个state变量的值永远不会在一次渲染的内部发生变化,即使其事件处理函数的代码是异步的。
  • 设置state不会更改现有渲染中的变量,但会请求一次新的渲染。
  • 我们应该把所有存放在state中的JavaScript对象都视为只读的。
  • 当我们在state中存放对象时,直接修改对象并不会触发重渲染,并会改变前一次渲染“快照”中 state 的值,所以不要直接修改一个对象,而要为它创建一个新版本,并通过把state设置成这个新版本来触发重新渲染。
  • 我们可以使用这样的 {…obj, something: ‘newValue’} 对象展开语法来创建对象的拷贝。
  • 我们可以可以使用filter()和map()来创建一个经过过滤或者变换的数组。
  • 你可以使用 Immer 来保持代码简洁。

加油,虽然是摘抄,但还是有一定意义的,最起码自己又复习一遍重点,每句也都能理解。

Web3学习笔记(三)React基础02

今天完成了props传递,条件渲染,渲染列表,如何保持组件纯粹,摘抄了如下笔记,用以增强记忆,亦方便日后查找。

  • React组件使用props来互相通信。每个父组件都可以提供props给它的子组件,从而将一些信息传递给子组件;
  • 要传递props,请将它们添加到JSX,就像使用HTML属性一样,如中的src一样;
  • <Card><Avatar /></Card>这样的嵌套JSX,将被视为Card组件的children prop;
  • 在JSX中,{cond && <A />}表示:“当 cond 为真值时, 渲染<A />,否则不进行渲染”;
  • 箭头函数 => { 后面的部分被称为 “块函数体”,块函数体支持多行代码的写法,但要用 return 语句才能指定返回值;
  • key值在兄弟节点之间必须是唯一的。不过不要求全局唯一,在不同的数组中可以使用相同的key;
  • 部分JavaScript函数是纯粹的,这类函数通常被称为纯函数。纯函数仅执行计算操作,不做其他操作。纯函数不会改变函数作用域外的变量、或在函数调用前创建的对象;
  • 纯函数输入相同,则输出相同。给定相同的输入,组件应该总是返回相同的JSX;
  • push、pop、reverse 和 sort 会改变原始数组,但 slice、filter 和 map 则会创建一个新数组。

接下来要学习添加交互的相关内容了,加油!

Web3学习笔记(二)React基础01

开始学习React了,我的计划是先把官方文档学习完,地址如下:

https://zh-hans.react.dev/learn

然后再看B站视频跟着做1~2个项目,计划用一周时间学完React和Next.js。

笔记也几乎是从官方文档整理的关键知识点,有些条目自己也做了一些补充知识点,这里再输出一遍,让自己记忆更加深刻。

Notes:

  1. React是用于构建Web和原生交互界面的JavaScript库,用组件创建用户界面,用代码和标签(JSX)编写组件。
  2. React是一个用于构建用户界面(UI)的JavaScript库,用户界面由按钮、文本和图像等小单元内容构建而成。React把它们组合成可重用、可嵌套的组件。
  3. React应用是由被称为组件的独立UI片段构建而成。React组件本质上是可以任意添加标签的JavaScript函数。组件可以小到一个按钮,也可以大到是整个页面。
  4. 每个React组件都是一个JavaScript函数,它可能包含一些标签,React会将其渲染到浏览器中。React组件使用一种叫做JSX的语法扩展来表示该标签。JSX看起来很像HTML,但它更为严格,可以显示动态信息。它们返回JSX标签。
  5. React组件是常规的JavaScript函数,但组件的名称必须以大写字母开头,否则它们将无法运行!引用时标签也必须大写,用以区分常规的html标签。
  6. 你应该在顶层定义每个组件,永远不要在组件中定义组件。
  7. 当子组件需要使用父组件的数据时,通过props的形式进行传递,而不是嵌套定义。
  8. 导出组件分默认和具名两种方式,导出组件时使用什么导出方式,则导入时,也需要使用相对应的导入方式。
  9. JSX规则,只能返回一个根元素,如果想要在一个组件中包含多个元素,需要用一个父标签把它们包裹起来,可使用空标签Fragment。
  10. 大括号让你可以将JavaScript 的逻辑和变量带入到标签中。它们会在JSX标签中的内容区域或紧随属性的=后起作用。
  11. {{ 和 }} 并不是什么特殊的语法:它只是包在JSX大括号内的JavaScript对象。

截止目前所学,整理如上知识点,加深理解,好方便后面做项目。

Web3学习笔记(一)技术栈梳理

这两天看了Web3开发入门课程,先把我自己理解的记录一下,等以后再回过头来看,我的理解是否准确。

首先说从Web2.0转型到Web3.0开发,适合的主要岗位有哪些:

  • DApp前端开发
  • 钱包开发
  • 智能合约开发
  • Web3全栈开发
  • 区块链后端开发
  • 区块链安全开发

我在Web2.0就算是全栈开发,所以这次目标就还是全栈开发或智能合约开发,太低层的以后再说,那要学习的技术栈有哪些呢?

目前我对前端的技术栈理解逐渐清晰,这里记录一下,后面一定要回过头看理解是否准确。

  • 前端页面构建
    • React,前端开发基础,需要掌握组件、状态管理(useState/useEffect)、JSX。
    • Next.js,是一个 React 开发框架,可以理解为React的增强版。
  • 与区块链交互
    • web3.js 这个太老了,不用。
    • ethers.js,比 web3.js 更轻量、更现代,代码更简洁。
    • viem,比 ethers.js 更轻量、速度更快,TypeScript支持更好。
    • wagmi,基于 ethers.js 或 viem 的封装,目前wagmi+view组合是,Web3开发的首选。

WalletConnect,是DApp与钱包之间的桥梁,用于连接这两样。

区块链和智能合约开发,截止到目前了解有限,只知道: – Solidity, 开发语言选 – Hardhat,智能合约开发框架

但还不很清楚它们之间的关联关系,后期一定会弄清楚,目前先把前端吃透。

Promise与async/await的区别

这次,彻底搞懂Promise和async/await。

Promise已经比传统的回调函数(Callback Hell)更先进,那后来为社么又出现async/await了呢?

async/await的出现是为了让异步代码写起来更像同步代码,解决Promise在复杂场景下的嵌套问题和可读性问题,让我们能更轻松地编写和维护异步逻辑。

Notes:
* async/await 底层仍然是 Promise,只是写法更简洁。
* await 只能在 async 函数中使用,否则会报错。
* async 函数总是返回 Promise。
* await 会阻塞当前 async 函数的执行,但不会阻塞整个程序。

举例: 比如入门Web3项目开发,必须要先学会Next.js、ethers.js、Solidity、Go, 才能做智能合约开发。基础代码如下:

function learnNextJs() {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log("1. 已完成 Next.js 学习");
            resolve();
        }, 1000);
    });
}

function learnEthersJs() {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log("2. 已完成 ethers.js 学习");
            resolve();
        }, 1500);
    });
}

function learnSolidity() {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log("3. 已完成 Solidity 学习");
            resolve();
        }, 2000);
    });
}

function learnGo() {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log("4. 已完成 Go 学习(可选)");
            resolve();
        }, 500);
    });
}

然后使用 Promise 链式调用(必须按顺序学习)

learnNextJs()
.then(() => learnEthersJs())
.then(() => learnSolidity())
.then(() => learnGo())
.then(() => {
    console.log("恭喜!你现在可以开发完整的 Web3 项目了!");
})
.catch((error) => {
    console.log("学习过程中出错:", error);
});

输出结果是:
1. 已完成 Next.js 学习
2. 已完成 ethers.js 学习
3. 已完成 Solidity 学习
4. 已完成 Go 学习(可选)
恭喜!你现在可以开发完整的 Web3 项目了!

那如果换成async/await方式呢?

async function web3LearningPath() {
    try {
        // 必须按顺序学习
        await learnNextJs();       // 等待第一步完成
        await learnEthersJs();    // 然后学习第二步
        await learnSolidity();    // 接着学习第三步
        
        // Go 是可选的,可以并行学习
        const optionalLearning = learnGo(); // 不等待,继续执行后面代码
        
        console.log("正在同时学习 Solidity 和 Go...");
        
        await optionalLearning; // 如果需要确保Go也学完才继续
        
        console.log("恭喜!你现在可以开发完整的 Web3 项目了!");
        
        // 现在可以开始智能合约开发了
        await startSmartContractDevelopment();
    } catch (error) {
        console.log("学习过程中出错:", error);
    }
}

// 启动学习流程
web3LearningPath();

async function startSmartContractDevelopment() {
    console.log("开始智能合约开发...");
}

则输出结果为:
1. 已完成 Next.js 学习
2. 已完成 ethers.js 学习
3. 已完成 Solidity 学习
正在同时学习 Solidity 和 Go…
4. 已完成 Go 学习(可选)
恭喜!你现在可以开发完整的 Web3 项目了!
开始智能合约开发…

最后:
Promise是基础,所有异步操作最终都是Promise,async/await是更优雅的写法,让异步代码更易读。在 Web3 开发中,大部分情况应使用async/await。

Web3入门词条整理

这两天学习了不少Web3的知识,东西太多,还是自己整理,输出一遍会记得更牢。记不住了,来这里查也很方便,两全其美:)

  • 区块链(Blockchain),区块链就像一个公共的“数字账本”,记录所有交易信息,并且这个账本由成千上万的电脑共同维护,而不是由某个公司或机构控制。
  • 公链(Public Blockchain),公链是所有人都能参与的区块链,就像互联网一样开放,任何人都可以读取、发送交易或参与维护。
  • 以太坊(Ethereum),以太坊是一个公链,但它比比特币更强大,支持“智能合约”(自动执行的程序),让开发者可以构建去中心化应用(DApp)。
  • 智能合约(Smart Contract),一段自动执行的代码,像“数字合同”,满足条件时自动运行,不需要中间人。
  • DEX(去中心化交易所,Decentralized Exchange),没有中间商的交易所,用户直接通过智能合约交易加密货币,资产始终由自己掌控。
  • DeFi(去中心化金融,Decentralized Finance),用区块链技术重建传统金融(借贷、交易、理财),去掉银行和券商,全部由代码自动运行。
  • DID(去中心化身份,Decentralized Identity),身份信息不再由大互联网公司掌控,而是由你自己管理,通过区块链验证。
  • DAO(去中心化自治组织,Decentralized Autonomous Organization),就像没有老板的公司,成员通过投票决定事务,规则写在智能合约里。
  • ABI(应用二进制接口,Application Binary Interface),智能合约和外部程序沟通的“翻译手册”,告诉你怎么调用合约里的函数。
  • IPFS(星际文件系统,InterPlanetary File System),去中心化的“云存储”,文件以碎片形式存在多台电脑上,不怕服务器宕机或审查。
  • NFT(非同质化代币,Non-Fungible Token),区块链上的“数字证书”,证明某个东西(如图片、音乐)是独一无二的。
  • DApp(去中心化应用,Decentralized Application),运行在区块链上的App,后端是智能合约,没有公司控制。
  • GAS(燃料费),在区块链上操作(如转账、执行合约)的手续费,奖励给维护网络的矿工。

当然,我在学习的过程中,还会接触到更多的词汇,后续我也会在此进行补充的,敬请关注。