<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>慕雨 Blog</title>
        <link>https://www.axin.work/</link>
        <description>这是一个由NotionNext生成的站点</description>
        <lastBuildDate>Mon, 10 Feb 2025 06:10:48 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-CN</language>
        <copyright>All rights reserved 2025, 慕雨</copyright>
        <item>
            <title><![CDATA[React笔记-核心概念]]></title>
            <link>https://www.axin.work/article/5cc20137-2f93-45e5-a9d5-27389e197ece</link>
            <guid>https://www.axin.work/article/5cc20137-2f93-45e5-a9d5-27389e197ece</guid>
            <pubDate>Sat, 28 May 2022 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-5cc201372f9345e5a9d527389e197ece"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-e7e2054f57014a67a335c2495db32fe0" data-id="e7e2054f57014a67a335c2495db32fe0"><span><div id="e7e2054f57014a67a335c2495db32fe0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e7e2054f57014a67a335c2495db32fe0" title="核心概念"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>核心概念</b></span></span></h2><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-c0412436ea194f55bebbc5cda1fc3766" data-id="c0412436ea194f55bebbc5cda1fc3766"><span><div id="c0412436ea194f55bebbc5cda1fc3766" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c0412436ea194f55bebbc5cda1fc3766" title="JSX简介"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>JSX简介</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e84bdab09b8741d38b1f552a1740c36f" data-id="e84bdab09b8741d38b1f552a1740c36f"><span><div id="e84bdab09b8741d38b1f552a1740c36f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e84bdab09b8741d38b1f552a1740c36f" title="什么是JSX？"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>什么是JSX？</b></span></span></h4><div class="notion-text notion-block-34804a6f2ef24f0e9aed13d76a3069b8">以类似模板语法的方式描述UI的一种语法。它是JS的<b>语法糖</b>，<b>本质上也是JS</b>。可以在其中使用<b>变量或表达式、函数等</b>。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ff8361ebe91e4188a33f9e557727a6ec" data-id="ff8361ebe91e4188a33f9e557727a6ec"><span><div id="ff8361ebe91e4188a33f9e557727a6ec" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ff8361ebe91e4188a33f9e557727a6ec" title="为什么使用JSX？"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>为什么使用JSX？</b></span></span></h4><div class="notion-text notion-block-eed77a83fd504047bdc789237db3cf69">将<em>标记与逻辑</em> 共同存放在称之为“组件”的松散耦合单元之中，来实现<em><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://en.wikipedia.org/wiki/Separation_of_concerns">关注点分离</a></em><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://en.wikipedia.org/wiki/Separation_of_concerns"> (opens new window)</a>。</div><div class="notion-text notion-block-b979b29420744cf09b31b113314dbeab">React不强制使用JSX，但在 JavaScript 代码中将 JSX 和 UI 放在一起时，会在<b>视觉上有辅助作用</b>。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-66dae59dfdf54796a1547d85c984900b" data-id="66dae59dfdf54796a1547d85c984900b"><span><div id="66dae59dfdf54796a1547d85c984900b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#66dae59dfdf54796a1547d85c984900b" title="在 JSX 中嵌入表达式"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>在 JSX 中嵌入表达式</b></span></span></h4><div class="notion-text notion-block-55ecec64d75a49a782811e457dbde171">在 JSX 语法中，你可以在大括号内放置任何有效的 <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Expressions">JavaScript 表达式 (opens new window)</a>。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-c14f1e1fef1042658048137977c73669" data-id="c14f1e1fef1042658048137977c73669"><span><div id="c14f1e1fef1042658048137977c73669" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c14f1e1fef1042658048137977c73669" title="JSX 也是一个表达式"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>JSX 也是一个表达式</b></span></span></h4><div class="notion-text notion-block-b0f9ae3d31bb4f6187b92b41dbfe9c85">在编译之后，JSX 表达式会被转为普通 JavaScript 函数调用，并且对其取值后<b>得到 JavaScript 对象</b></div><blockquote class="notion-quote notion-block-a4798fe10f4945e39b71f0f1af03c915"><div>可以把JSX当初一个对象来对待，可以使用它赋值给变量、当参数输入函数、返回JSX等。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-633163d7d17b449ca24b90d3f209a90c" data-id="633163d7d17b449ca24b90d3f209a90c"><span><div id="633163d7d17b449ca24b90d3f209a90c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#633163d7d17b449ca24b90d3f209a90c" title="JSX 特定属性"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>JSX 特定属性</b></span></span></h4><div class="notion-text notion-block-1f26f683f9904b2d8c96f387f47027b9">通过使用引号，来将属性值指定为字符串字面量：</div><blockquote class="notion-quote notion-block-ba728f2a0aa44410ac9ded39e2ef3fa7"><div>JSX中的属性名使用camelCase(小驼峰)命名。如上面例子中的tabIndex</div></blockquote><div class="notion-text notion-block-1e650a00411e4f0194e47f82dc80dc07">使用大括号，来在属性值中插入一个 JavaScript 表达式：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ab00940b6a5644e7922dcb464dcdee71" data-id="ab00940b6a5644e7922dcb464dcdee71"><span><div id="ab00940b6a5644e7922dcb464dcdee71" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ab00940b6a5644e7922dcb464dcdee71" title="使用 JSX 指定子元素"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>使用 JSX 指定子元素</b></span></span></h4><div class="notion-text notion-block-513e1ab615834962929039a6490f403f">JSX 标签里能够包含很多子元素:</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-536e908510644adc974c317a9fdc3d87" data-id="536e908510644adc974c317a9fdc3d87"><span><div id="536e908510644adc974c317a9fdc3d87" class="notion-header-anchor"></div><a class="notion-hash-link" href="#536e908510644adc974c317a9fdc3d87" title="JSX 防止注入攻击"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>JSX 防止注入攻击</b></span></span></h4><div class="notion-text notion-block-159329c2037c4f5cb66986a6e567f12b">React DOM 在渲染所有输入内容之前，默认会进行<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-on-html">转义 (opens new window)</a>。它可以确保在你的应用中，<b>永远不会注入那些并非自己明确编写的内容</b>。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://en.wikipedia.org/wiki/Cross-site_scripting">XSS（cross-site-scripting, 跨站脚本） (opens new window)</a>攻击。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-5f3aeda2fbbb43c2bda0b2767c75bd70" data-id="5f3aeda2fbbb43c2bda0b2767c75bd70"><span><div id="5f3aeda2fbbb43c2bda0b2767c75bd70" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5f3aeda2fbbb43c2bda0b2767c75bd70" title="JSX 表示对象"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>JSX 表示对象</b></span></span></h4><div class="notion-text notion-block-6da29e1dea654bfd8040cab4e5270e7c">Babel 会把 JSX 转译成一个名为 <code class="notion-inline-code">React.createElement()</code> 函数调用。</div><div class="notion-text notion-block-ccbc8199ef3047b2908183c0e4af0a49">以下两种示例代码完全等效：</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-a5fc156e0e7e49f7b334cf650cc47499" data-id="a5fc156e0e7e49f7b334cf650cc47499"><span><div id="a5fc156e0e7e49f7b334cf650cc47499" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a5fc156e0e7e49f7b334cf650cc47499" title="元素渲染"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>元素渲染</b></span></span></h3><div class="notion-text notion-block-b43882d0312544ebaafe37306f6da7b5">元素是构成 React 应用的最小砖块，描述了你在屏幕上想看到的内容。</div><div class="notion-text notion-block-66ec384205394cf18c2a280727da09aa">与浏览器的 DOM 元素不同，<b>React 元素是创建开销极小的普通对象</b>。React DOM 会负责更新 DOM 来与 React 元素保持一致。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-59930010d0de4a5a901511222d1dcae6" data-id="59930010d0de4a5a901511222d1dcae6"><span><div id="59930010d0de4a5a901511222d1dcae6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#59930010d0de4a5a901511222d1dcae6" title="将一个元素渲染为 DOM"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>将一个元素渲染为 DOM</b></span></span></h4><div class="notion-text notion-block-d1d4851240e142e5bed62f5166632e4a">假设你的 HTML 文件某处有一个 <code class="notion-inline-code">&lt;div&gt;</code>：</div><div class="notion-text notion-block-de3ccfd2456e4915b1041dbc96591d3b">根节点，React应用一般只有单一根DOM节点</div><blockquote class="notion-quote notion-block-5ec14866ce6842388fbdf6e098d3e9a6"><div>但一个html页面可以有多个React应用，每个应用对应一个独立根节点。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2f83f24f01784bb4b1b10dbdda3524b5" data-id="2f83f24f01784bb4b1b10dbdda3524b5"><span><div id="2f83f24f01784bb4b1b10dbdda3524b5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2f83f24f01784bb4b1b10dbdda3524b5" title="更新已渲染的元素"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>更新已渲染的元素</b></span></span></h4><div class="notion-text notion-block-390e0a5a9a6d4d568c9bbe39d546439f">React 元素是<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://en.wikipedia.org/wiki/Immutable_object">不可变对象 (opens new window)</a>。一旦被创建，你就无法更改它的子元素或者属性。一个元素就像电影的单帧：它代表了某个特定时刻的 UI。</div><div class="notion-text notion-block-a6d81d9fbb504b7282ba56c62dea3882">根据我们已有的知识，更新 UI 唯一的方式是创建一个全新的元素，并将其传入 <code class="notion-inline-code">root.render()</code>。</div><div class="notion-text notion-block-df8749cddc604804b8ef73fcd13f270e">考虑一个计时器的例子：</div><div class="notion-text notion-block-f76e129302904623933e0f1cda934767">注意：在实践中，<b>大多数 React 应用只会调用一次 root.render()</b>。在下一个章节，我们将学习如何将这些代码封装到<b><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/state-and-lifecycle.html">有状态组件 (opens new window)</a></b>中。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-6f4e8a4be7274128ab4d17e4eeb04760" data-id="6f4e8a4be7274128ab4d17e4eeb04760"><span><div id="6f4e8a4be7274128ab4d17e4eeb04760" class="notion-header-anchor"></div><a class="notion-hash-link" href="#6f4e8a4be7274128ab4d17e4eeb04760" title="React 只更新它需要更新的部分"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>React 只更新它需要更新的部分</b></span></span></h4><div class="notion-text notion-block-4819a3b00b6647e5b57233da191ffb6b">上个例子中，尽管每一秒我们都会新建一个描述整个 UI 树的元素，但React DOM <b>只会更新实际改变了的内</b>容。</div><blockquote class="notion-quote notion-block-8b36ecad743b4970b98110e391c28ea3"><div>注意：react 18版本 已移除原 ReactDOM.render 方法，以 createRoot 代替。</div></blockquote><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-ca1caead26eb4bc2b3be94c8d004694b" data-id="ca1caead26eb4bc2b3be94c8d004694b"><span><div id="ca1caead26eb4bc2b3be94c8d004694b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ca1caead26eb4bc2b3be94c8d004694b" title="组件&amp;Props"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>组件&amp;Props</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-5a092e975db94743bd81b6e67214dd58" data-id="5a092e975db94743bd81b6e67214dd58"><span><div id="5a092e975db94743bd81b6e67214dd58" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5a092e975db94743bd81b6e67214dd58" title="函数组件与 class 组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>函数组件与 class 组件</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-01c02a142f2d4bef80fe712bc4200c8a" data-id="01c02a142f2d4bef80fe712bc4200c8a"><span><div id="01c02a142f2d4bef80fe712bc4200c8a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#01c02a142f2d4bef80fe712bc4200c8a" title="1.函数组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1.函数组件</b></span></span></h4><div class="notion-text notion-block-838ce77083cc445aba4a44ccceb407ec">该函数是一个有效的React组件。接收唯一带有数据的props参数，并返回一个React元素。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-40b8c892284e466bbf3beaaf9de3077d" data-id="40b8c892284e466bbf3beaaf9de3077d"><span><div id="40b8c892284e466bbf3beaaf9de3077d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#40b8c892284e466bbf3beaaf9de3077d" title="2.class组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.class组件</b></span></span></h4><div class="notion-text notion-block-54ded2a75f894200ae1b5b879871f2bc">使用ES6的class来定义：</div><div class="notion-text notion-block-38171774ed6e4663bbc3ed23aa43ea9d">以上两个组件是等效的。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2ef637030a6b4eecbee6783c1871670d" data-id="2ef637030a6b4eecbee6783c1871670d"><span><div id="2ef637030a6b4eecbee6783c1871670d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2ef637030a6b4eecbee6783c1871670d" title="函数组件与Class组件在事件处理上的一些区别"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>函数组件与Class组件在事件处理上的一些区别</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-65754d8dd16842c8b3dcef64a37e50ba"><li>使用<code class="notion-inline-code">class组件</code>时的事件处理： <code class="notion-inline-code">onClick={() =&gt; this.props.onClick()}</code></li></ul><ul class="notion-list notion-list-disc notion-block-5477aa8b40bc42328c0a1456d543b8cf"><li>使用<code class="notion-inline-code">函数组件</code>时的事件处理： <code class="notion-inline-code">onClick={props.onClick}</code>（注意两侧<em>都</em>没有括号）。</li></ul><div class="notion-text notion-block-b4184ebaa5fb4301a7e7758caf87e1f2">class组件特点：</div><ul class="notion-list notion-list-disc notion-block-2ed1d00ce39f40cfb6ecaf226ce40ba7"><li>有组件实例</li></ul><ul class="notion-list notion-list-disc notion-block-42975586f98c4fc4936741886fb1785d"><li>有生命周期</li></ul><ul class="notion-list notion-list-disc notion-block-fd7cea57aacc443ba31833d54e06d77a"><li>有 state 和 setState</li></ul><div class="notion-text notion-block-3e2278acc5fd4aaa86f750cfa4c1a692">函数组件特点：</div><ul class="notion-list notion-list-disc notion-block-65f6b1d7ac4b47279b2f6853149019bd"><li>没有组件实例</li></ul><ul class="notion-list notion-list-disc notion-block-3825042db2fe4fa8a097b46872853371"><li>没有生命周期</li></ul><ul class="notion-list notion-list-disc notion-block-0bfa7c8ca8694527947e5573941eac54"><li>没有 state 和 setState，只能接收 props</li></ul><ul class="notion-list notion-list-disc notion-block-86240abb28f845ef9fc4ed6328524bef"><li>函数组件是一个纯函数，执行完即销毁，无法存储 state</li></ul><div class="notion-text notion-block-556b5f58dfa242f19de252fcbba120da">class 组件存在的问题：</div><ul class="notion-list notion-list-disc notion-block-b0a3cf43fd0c44a389945de4bb418f6d"><li>大型组件很难拆分和重构，变得难以测试</li></ul><ul class="notion-list notion-list-disc notion-block-4342e193397d48d7a49bc61851cf6c35"><li>相同业务逻辑分散到各个方法中，可能会变得混乱</li></ul><ul class="notion-list notion-list-disc notion-block-f836ce2a078b467194f8c1bd82696bfc"><li>复用逻辑可能变得复杂，如 HOC 、Render Props</li></ul><blockquote class="notion-quote notion-block-0a64240da21d404eb6fd6dcb8ded39a9"><div>所以 react 中更提倡函数式编程，因为函数更灵活，更易拆分，但函数组件太简单，所以出现了hook，hook就是用来增强函数组件功能的。</div><div class="notion-text notion-block-964c9a5b5c4c4f6fa4c3b3f9ca252c5f">类组件功能最为完备和强大，某些特殊用途(如错误边界)组件只能写成类式组件。函数组件没有this困扰且代码简洁，大部分的普通组件都可以写成函数组件。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-433cced008364dfb95bf3a33527fe5f2" data-id="433cced008364dfb95bf3a33527fe5f2"><span><div id="433cced008364dfb95bf3a33527fe5f2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#433cced008364dfb95bf3a33527fe5f2" title="属性展开运算符"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>属性展开运算符</b></span></span></h4><div class="notion-text notion-block-5342469a5cea4c799ced23cdc6d0b120">如果你已经有了一个 props 对象，你可以使用<b>展开运算符 ...</b>来在 JSX 中传递整个 props 对象。以下两个组件是等价的：</div><div class="notion-text notion-block-9f8d63d35c6f4751b60c3baf6ca6f1f6">还可以选择只保留当前组件需要接收的 props，并使用展开运算符将其他 props 传递下去。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e4e713dad8494aceacc3a0213a6512dc" data-id="e4e713dad8494aceacc3a0213a6512dc"><span><div id="e4e713dad8494aceacc3a0213a6512dc" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e4e713dad8494aceacc3a0213a6512dc" title="渲染组件（父子组件传值）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>渲染组件（父子组件传值）</b></span></span></h4><div class="notion-text notion-block-7d2b6f2cc98c4bac8e5d55e1444ec0f5">React 元素也可以是用户自定义的组件：</div><div class="notion-text notion-block-58752d70deae43b1b8c9f34fc2805a03">通过属性（attributes）来传递值给子组件：</div><div class="notion-text notion-block-07340258e8e24e2c95113ecd73c8c402"><b>注意：</b> <b>组件名称必须以大写字母开头。</b></div><div class="notion-text notion-block-d17a0559205e44a38f14cb983bcbbe06">React 会将以小写字母开头的组件视为原生 DOM 标签。例如，<code class="notion-inline-code">&lt;div /&gt;</code> 代表 HTML 的 div 标签，而 <code class="notion-inline-code">&lt;Welcome /&gt;</code> 则代表一个组件，并且需在作用域内使用 <code class="notion-inline-code">Welcome</code>。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2bc59a44ee434662ba80914942a54452" data-id="2bc59a44ee434662ba80914942a54452"><span><div id="2bc59a44ee434662ba80914942a54452" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2bc59a44ee434662ba80914942a54452" title="组合组件（复用组件）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>组合组件（复用组件）</b></span></span></h4><blockquote class="notion-quote notion-block-67f39c2756324ed1b6050b2330ae5daf"><div>通常来说，每个新的 React 应用程序的顶层组件都是 App 组件</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2bb62d8c5dae4d69b4ad9d16befa8c68" data-id="2bb62d8c5dae4d69b4ad9d16befa8c68"><span><div id="2bb62d8c5dae4d69b4ad9d16befa8c68" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2bb62d8c5dae4d69b4ad9d16befa8c68" title="提取组件（拆分组件）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>提取组件（拆分组件）</b></span></span></h4><div class="notion-text notion-block-b94ff4107c6f489689489764bc142220">参考如下 <code class="notion-inline-code">Comment</code> 组件：</div><div class="notion-text notion-block-bfde4fa6e4cd444b902438abd2e57856">该组件由于嵌套的关系，变得难以维护，且很难复用它的各个部分。因此，让我们从中提取一些组件出来。</div><div class="notion-text notion-block-d8adf0eea73b400cbf0eaeb1900447a7">首先，提取 <code class="notion-inline-code">Avatar</code> 组件：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1187c0f118b94f19babbe20ea4dc101c" data-id="1187c0f118b94f19babbe20ea4dc101c"><span><div id="1187c0f118b94f19babbe20ea4dc101c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1187c0f118b94f19babbe20ea4dc101c" title="props命名原则"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>props命名原则</b></span></span></h4><div class="notion-text notion-block-366031b0bdd040aea40e03f482f6ece2"><code class="notion-inline-code">Avatar</code> 不需知道它在 <code class="notion-inline-code">Comment</code> 组件内部是如何渲染的。因此，我们给它的 props 起了一个更通用的名字：<code class="notion-inline-code">user</code>，而不是 <code class="notion-inline-code">author</code>。</div><div class="notion-text notion-block-42f56eb225dc4e5b83b96af3a8269bc8">我们<b>建议从组件自身的角度命名 props，而不是依赖于调用组件的上下文命名</b>。</div><div class="notion-text notion-block-219631a75dc64b04a382d409774c527b">接下来，我们将提取 <code class="notion-inline-code">UserInfo</code> 组件，该组件在用户名旁渲染 <code class="notion-inline-code">Avatar</code> 组件：</div><div class="notion-text notion-block-a32ef374c5af4902a45e26be5e58fb1c">最终的 <code class="notion-inline-code">Comment</code> 组件：</div><div class="notion-text notion-block-6f3c61ae696e4d14a498f82c2b73b583">最初看上去，提取组件可能是一件繁重的工作，但是，在大型应用中，构建可复用组件库是完全值得的。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-06b379a5636448489b5ba171a3aa069b" data-id="06b379a5636448489b5ba171a3aa069b"><span><div id="06b379a5636448489b5ba171a3aa069b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#06b379a5636448489b5ba171a3aa069b" title="提取原则"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>提取原则</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-8bdbe167ba624f049a06e16b0c594406"><li>UI中多次被使用的部分</li></ul><ul class="notion-list notion-list-disc notion-block-553ca7267455412894bcd893602445c1"><li>一个足够复杂的组件（页面）</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7b04086f3e9d475cacd85d17e13921dc" data-id="7b04086f3e9d475cacd85d17e13921dc"><span><div id="7b04086f3e9d475cacd85d17e13921dc" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7b04086f3e9d475cacd85d17e13921dc" title="Props 的只读性（不能修改Props）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Props 的只读性（不能修改Props）</b></span></span></h4><div class="notion-text notion-block-70344edfa6ac464f9dba1d6a34409eab">组件无论是使用<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/components-and-props.html#function-and-class-components">函数声明还是通过 class 声明 (opens new window)</a>，都决不能修改自身的 props。</div><blockquote class="notion-quote notion-block-18784d4f734c419cba961a39e639efcb"><div>当然，应用程序的 UI 是动态的，并会伴随着时间的推移而变化。在下一章节 (opens new window)中，我们将介绍一种新的概念，称之为 “state”。在不违反上述规则的情况下，state 允许 React 组件随用户操作、网络响应或者其他变化而动态更改输出内容</div></blockquote><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-e0e03b01608d49dcb02dfb55eeb84c8d" data-id="e0e03b01608d49dcb02dfb55eeb84c8d"><span><div id="e0e03b01608d49dcb02dfb55eeb84c8d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e0e03b01608d49dcb02dfb55eeb84c8d" title="State&amp;生命周期"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>State&amp;生命周期</b></span></span></h3><div class="notion-text notion-block-0a36fd8bde7a43f1b636de68d1a8fad0">State 与 props 类似，但是 <b>state 是私有的，并且完全受控于当前组件.</b></div><blockquote class="notion-quote notion-block-20734ce5d1b84bd4b6485edf97f24d54"><div>State类似于vue中的data选项</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7c494c12055d402db9dd569626139a1f" data-id="7c494c12055d402db9dd569626139a1f"><span><div id="7c494c12055d402db9dd569626139a1f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7c494c12055d402db9dd569626139a1f" title="生命周期"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>生命周期</b></span></span></h4><div class="notion-text notion-block-349ef9a9a83e44d1b01adc4ed25eb324">React16 自上而下地对生命周期做了另一种维度的解读：</div><ul class="notion-list notion-list-disc notion-block-b373d4a8791742b191865bd1cf8ac4d4"><li><b>Render阶段：</b>计算一些必要的状态信息。</li></ul><ul class="notion-list notion-list-disc notion-block-99f2494a42e44709a22adeaf3e64107f"><li><b>Pre-commit阶段：</b>这里指的是“更新真正的 DOM 节点”这个动作。该阶段并没有去更新真实的 DOM，不过 DOM 信息已经是可以读取(包括 ref)。</li></ul><ul class="notion-list notion-list-disc notion-block-101e3453153d46638ca0fb107c246eb3"><li><b>Commit 阶段</b>：React 会完成真实 DOM 的更新工作。</li></ul><div class="notion-text notion-block-0ddfd92068d04c5994051ad8d1479341">与此同时，新的生命周期在流程方面，仍然遵循“挂载”、“更新”、“卸载”这三个广义的划分方式。它们分别对应到：</div><div class="notion-text notion-block-eaccf0c344d7474092fdb344806c2099"><b>挂载过程：</b></div><ul class="notion-list notion-list-disc notion-block-982f8fbdad4d4dfda3d4c668f745aa1d"><li>constructor</li></ul><ul class="notion-list notion-list-disc notion-block-8d1581b539d349a480880a90179a8324"><li>getDerivedStateFromProps</li></ul><ul class="notion-list notion-list-disc notion-block-3ca036a7d21f4bdf80eefc15d7097b52"><li>render</li></ul><ul class="notion-list notion-list-disc notion-block-52761c6dfca347fc90ef6f53f71181f4"><li>componentDidMount</li></ul><div class="notion-text notion-block-9bc6acb753f0402aa36fa1dda0e4a2a8"><b>更新过程：</b></div><ul class="notion-list notion-list-disc notion-block-adeb4e68bb274ac2900cae5468d1723b"><li>getDerivedStateFromProps</li></ul><ul class="notion-list notion-list-disc notion-block-ec4a23dde04b42a48ac1050d2012ae72"><li>shouldComponentUpdate</li></ul><ul class="notion-list notion-list-disc notion-block-d8e4e181534d4dfe82b50e24a4d0199c"><li>render</li></ul><ul class="notion-list notion-list-disc notion-block-b5ae88c01c6a492f890e02ea41398797"><li>getSnapshotBeforeUpdate</li></ul><ul class="notion-list notion-list-disc notion-block-87b5c6bfbf094003a7e01770ddc60de0"><li>componentDidUpdate</li></ul><div class="notion-text notion-block-b9744748b6dd498c9b7854348426cf2f"><b>卸载过程：</b></div><ul class="notion-list notion-list-disc notion-block-ceedca09ca204170bb89cddba2ecbf2a"><li>componentWillUnmount</li></ul><div class="notion-text notion-block-1203fb40f18180619b05f46355e5082a"><code class="notion-inline-code"><b>新</b></code></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1203fb40f181801fa3e0d5f008f8bdcc"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F2c930dfe-da21-46e5-a4f5-114f9750f2d0%2F80623e0e-99f3-437e-832e-e56a36c371f0%2F04-%25E7%2594%259F%25E5%2591%25BD%25E5%2591%25A8%25E6%259C%259F(%25E6%2596%25B0).png?table=block&amp;id=1203fb40-f181-801f-a3e0-d5f008f8bdcc&amp;t=1203fb40-f181-801f-a3e0-d5f008f8bdcc&amp;width=658.9921875&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1203fb40f181801496cbde57d2de8ed6"><code class="notion-inline-code"><b>旧</b></code></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1203fb40f1818090bb40ef86903649c4"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:528px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F2c930dfe-da21-46e5-a4f5-114f9750f2d0%2F6ed31b06-4f3b-4edc-a427-df201bad1aac%2F02-%25E7%2594%259F%25E5%2591%25BD%25E5%2591%25A8%25E6%259C%259F(%25E6%2597%25A7).png?table=block&amp;id=1203fb40-f181-8090-bb40-ef86903649c4&amp;t=1203fb40-f181-8090-bb40-ef86903649c4&amp;width=528&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-1203fb40f1818004ad4ec3790d38d111"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-52a9111e83f347f8ad0b0895e44d6058" data-id="52a9111e83f347f8ad0b0895e44d6058"><span><div id="52a9111e83f347f8ad0b0895e44d6058" class="notion-header-anchor"></div><a class="notion-hash-link" href="#52a9111e83f347f8ad0b0895e44d6058" title="将函数组件转换成 class 组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>将函数组件转换成 class 组件</b></span></span></h4><blockquote class="notion-quote notion-block-31d602a6ee844b0abfa3f06f69bc97ad"><div>在没有useState钩子函数之前，是通过class组件管理State ？</div></blockquote><div class="notion-text notion-block-66806a33cc0f45a1995afd247a4eb0f4">每次组件更新时 <code class="notion-inline-code">render</code> 方法都会被调用，但只要在相同的 DOM 节点中渲染 <code class="notion-inline-code">&lt;Clock /&gt;</code> ，就<b>仅有一个 </b><code class="notion-inline-code"><b>Clock</b></code><b> 组件的 class 实例被创建使用</b>。这就使得我们可以使用如 state 或生命周期方法等很多其他特性。</div><blockquote class="notion-quote notion-block-3631e9dabeef4ffbbf7f3db2ee18aed0"><div>单例模式？</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-6051d64a82d0414f9a885147f7ebd0b8" data-id="6051d64a82d0414f9a885147f7ebd0b8"><span><div id="6051d64a82d0414f9a885147f7ebd0b8" class="notion-header-anchor"></div><a class="notion-hash-link" href="#6051d64a82d0414f9a885147f7ebd0b8" title="向 class 组件中添加局部的 state"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>向 class 组件中添加局部的 state</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-881a816d3a5c42cc88c6701cb9a3920d" data-id="881a816d3a5c42cc88c6701cb9a3920d"><span><div id="881a816d3a5c42cc88c6701cb9a3920d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#881a816d3a5c42cc88c6701cb9a3920d" title="将生命周期方法添加到 Class 中"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>将生命周期方法添加到 Class 中</b></span></span></h4><div class="notion-text notion-block-5db326e722fc4e4c9782c78481b869cb">在具有许多组件的应用程序中，当组件被销毁时释放所占用的资源是非常重要的。</div><div class="notion-text notion-block-1445975b593246d48f5844abae2141a9">当 <code class="notion-inline-code">Clock</code> 组件第一次被渲染到 DOM 中的时候，就为其<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval">设置一个计时器 (opens new window)</a>。这在 React 中被称为“<b>挂载（mount）</b>”。</div><div class="notion-text notion-block-ecb958f0286d4050bea5dde705fe1d51">同时，当 DOM 中 <code class="notion-inline-code">Clock</code> 组件被删除的时候，应该<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/clearInterval">清除计时器 (opens new window)</a>。这在 React 中被称为“<b>卸载（unmount）</b>”。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-abd37fe566564af2999481cd5d31f19b" data-id="abd37fe566564af2999481cd5d31f19b"><span><div id="abd37fe566564af2999481cd5d31f19b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#abd37fe566564af2999481cd5d31f19b" title="正确地使用 State"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>正确地使用 State</b></span></span></h4><div class="notion-text notion-block-a7f2df37a2464f16a21b20414a0ef007">关于 <code class="notion-inline-code">setState()</code> 你应该了解三件事：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e35dc837b3864d0e892d4bc2c6f7ac88" data-id="e35dc837b3864d0e892d4bc2c6f7ac88"><span><div id="e35dc837b3864d0e892d4bc2c6f7ac88" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e35dc837b3864d0e892d4bc2c6f7ac88" title="不要直接修改 State"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>不要直接修改 State</b></span></span></h4><div class="notion-text notion-block-aacecefbce6a4c168b39db997f0615af"><b>构造函数是唯一可以给 </b><code class="notion-inline-code"><b>this.state</b></code><b> 直接赋值的地方</b></div><blockquote class="notion-quote notion-block-53dc0fa56feb4f56917dbb61d2bb40ed"><div>setState是React内部方法，使state更新具有响应式？</div></blockquote><div class="notion-text notion-block-74944146b6a84cfeb8b13a4ebfa24676">这是框架设计之初刻意为之，react通过迫使你调用setState去更新视图是为了让你意识到你正在改变组件的状态。</div><div class="notion-text notion-block-a3e47c16d5c84bf697ae2e9175fcb78a">这样可以让开发者在潜意识中认为改变state是一件严肃的事情，一定程度上规范开发行为。</div><div class="notion-text notion-block-2eb51e85eae54ce2804a03bb2d5bb748">以上是setState为什么存在，下面我们来看它的意义。</div><div class="notion-text notion-block-88757124468c4915af5b72679168434e"><b>1.任务驱动的更新</b></div><div class="notion-text notion-block-cfd1ba3e741d4425b839824af01cee3a">react实现更新的原理并不是vue那样的双向绑定，<code class="notion-inline-code">（vue用的是gettet和setter（3.0用的Proxy），在你赋值时它就知道哪个字段变了，于是也就知道该更新哪个组件）</code>而是在你设置state之后，随之产生一个更新任务，任务的出现触发更新调度。setState的作用正是去创建任务，标记哪个fiber节点产生了更新，并触发任务调度。如果直接修改，对象变了，但还是同一个对象，react并不知道数据已经变了。</div><div class="notion-text notion-block-06edaa951eb24bdebf88e209a0a3df59"><b>2.任务优先级</b></div><div class="notion-text notion-block-b711565fef194cd6b2c11b5f6c942542">setState创建更新时要从scheduler中拿到触发本次更新的优先级，将优先级加入到任务中。</div><div class="notion-text notion-block-23ed32297ffb44d687e64a1cc5542063">setState作为更新的入口，它是任务下发的起点。也不是说直接改变state就完全不能实现上述两点，但直接改变state想必是要有依赖收集的过程，但react中并不存在依赖收集，直接改了就是改了，并没有触发任何更新相关的流程。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e819550f956f4ffc9f919fede8f06679" data-id="e819550f956f4ffc9f919fede8f06679"><span><div id="e819550f956f4ffc9f919fede8f06679" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e819550f956f4ffc9f919fede8f06679" title="State 的更新可能是异步的"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>State 的更新可能是异步的</b></span></span></h4><div class="notion-text notion-block-4ebf71c539a44d70be6bd750f1bf510f">出于性能考虑，React 可能会把多个 <code class="notion-inline-code">setState()</code> 调用合并成一个调用。</div><div class="notion-text notion-block-f4682290cf884b99b3ab76c3a82a2700">因为 <code class="notion-inline-code">this.props</code> 和 <code class="notion-inline-code">this.state</code> 可能会异步更新，所以你<b>不要依赖他们的值来更新下一个状态</b>。</div><div class="notion-text notion-block-837771cccfbd473497d749dfa11284aa">要<b>解决这个问题，可以让 </b><code class="notion-inline-code"><b>setState()</b></code><b> 接收一个函数而不是一个对象</b>。这个函数用上一个 state 作为第一个参数，将此次更新被应用时的 props 做为第二个参数：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-39025417a1d843d4be08a7a3b4715b57" data-id="39025417a1d843d4be08a7a3b4715b57"><span><div id="39025417a1d843d4be08a7a3b4715b57" class="notion-header-anchor"></div><a class="notion-hash-link" href="#39025417a1d843d4be08a7a3b4715b57" title="State 的更新会被合并"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>State 的更新会被合并</b></span></span></h4><div class="notion-text notion-block-8ab70040d2de4e5aaa48c36bde24a310">当你调用 <code class="notion-inline-code">setState()</code> 的时候，React 会把你提供的对象合并到当前的 state。</div><div class="notion-text notion-block-4519e1c9c5594d82941970f6cf54098a">这里的合并是浅合并，所以 <code class="notion-inline-code">this.setState({comments})</code> 完整保留了 <code class="notion-inline-code">this.state.posts</code>， 但是完全替换了 <code class="notion-inline-code">this.state.comments</code>。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-b1abe27284814f28b67a4380c998927f" data-id="b1abe27284814f28b67a4380c998927f"><span><div id="b1abe27284814f28b67a4380c998927f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b1abe27284814f28b67a4380c998927f" title="数据是向下流动的（单向数据流）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>数据是向下流动的（单向数据流）</b></span></span></h4><div class="notion-text notion-block-097415e8b1a34e059d83a4bbe3454bd6">不管是父组件或是子组件都无法知道某个组件是有状态的还是无状态的，并且它们也并不关心它是函数组件还是 class 组件。</div><div class="notion-text notion-block-4e10b03948314b8eb86dbcb6ed31df1c">这就是为什么称 <b>state 为局部的</b>或是封装的的原因。除了拥有并设置了它的组件，<b>其他组件都无法访问</b>。</div><div class="notion-text notion-block-0493535cae474b5dae9a351d88465ec2">组件可以选择把它的 state 作为 props 向下传递到它的子组件中：</div><div class="notion-text notion-block-cad80b551a7540c19535fb40d5d55ad5"><code class="notion-inline-code">FormattedDate</code> 组件会在其 props 中接收参数 <code class="notion-inline-code">date</code>，但是<b>组件本身无法知道它是来自于 </b><code class="notion-inline-code"><b>Clock</b></code><b> 的 state，或是 </b><code class="notion-inline-code"><b>Clock</b></code><b> 的 props，还是手动输入的</b>。</div><div class="notion-text notion-block-188ed86423944db392a4990f068e77e1">这通常会被叫做“自上而下”或是<b>“单向”的数据流</b>。任何的 <b>state 总是所属于特定的组件</b>，而且从该 state 派生的任何数据或 UI 只能影响树中“低于”它们的组件。</div><div class="notion-text notion-block-dbfced4a6b5e44bb9df275296dd1693e">如果你把一个以组件构成的树想象成一个 props 的数据瀑布的话，那么每一个组件的 state 就像是在任意一点上给瀑布增加额外的水源，但是它只能向下流动。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-56ef8110b7434fa182d84c1abfdf9b5f" data-id="56ef8110b7434fa182d84c1abfdf9b5f"><span><div id="56ef8110b7434fa182d84c1abfdf9b5f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#56ef8110b7434fa182d84c1abfdf9b5f" title="每个组件都是真正独立的。"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>每个组件都是真正独立的。</b></span></span></h4><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-df2b7af554754050af2b836ebb9e3d21" data-id="df2b7af554754050af2b836ebb9e3d21"><span><div id="df2b7af554754050af2b836ebb9e3d21" class="notion-header-anchor"></div><a class="notion-hash-link" href="#df2b7af554754050af2b836ebb9e3d21" title="事件处理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>事件处理</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7bd4126ec3c54c4aacc7b63f75f770dc" data-id="7bd4126ec3c54c4aacc7b63f75f770dc"><span><div id="7bd4126ec3c54c4aacc7b63f75f770dc" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7bd4126ec3c54c4aacc7b63f75f770dc" title="与传统HTML绑定事件的区别"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>与传统HTML绑定事件的区别</b></span></span></h4><div class="notion-text notion-block-f3aa72278b8c431097b590594107575a">传统的 HTML：</div><div class="notion-text notion-block-9520e713d8094910bbf67e4d347e4898">在 React 中略微不同：</div><ul class="notion-list notion-list-disc notion-block-18ea0720a055435080696efaae8232fa"><li>React 事件的命名采用小驼峰式（camelCase），而不是纯小写。</li></ul><ul class="notion-list notion-list-disc notion-block-fec133235c294a2bbf76a01e6a485662"><li>使用 JSX 语法时你需要传入一个函数作为事件处理函数，而不是一个字符串。</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-b11fd4d4105048efbb2cf062d049a36b" data-id="b11fd4d4105048efbb2cf062d049a36b"><span><div id="b11fd4d4105048efbb2cf062d049a36b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b11fd4d4105048efbb2cf062d049a36b" title="阻止默认事件 (合成事件对象)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>阻止默认事件 (合成事件对象)</b></span></span></h4><div class="notion-text notion-block-ec958f49cbbc4b0386459b516699d635">在 React 中，你需要这样阻止默认事件：</div><div class="notion-text notion-block-a4b63c3a0c9b4ce9b749703f6c16d9ec">在这里，<code class="notion-inline-code">e</code> 是一个<b>合成事件</b>。React 根据 <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://www.w3.org/TR/DOM-Level-3-Events/">W3C 规范 (opens new window)</a>来定义这些合成事件，所以你不需要担心跨浏览器的兼容性问题。React 事件与原生事件不完全相同。如果想了解更多，请查看 <code class="notion-inline-code"><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/events.html">SyntheticEvent</a></code><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/events.html"> (opens new window)</a>参考指南。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-9dbea8b4b03846dba273f7c1188b0bcd" data-id="9dbea8b4b03846dba273f7c1188b0bcd"><span><div id="9dbea8b4b03846dba273f7c1188b0bcd" class="notion-header-anchor"></div><a class="notion-hash-link" href="#9dbea8b4b03846dba273f7c1188b0bcd" title="绑定事件的方式"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>绑定事件的方式</b></span></span></h4><div class="notion-text notion-block-1fcd5f0e18524a4996e9255848496788">使用 React 时，你一般不需要使用 <code class="notion-inline-code">addEventListener</code> 为已创建的 DOM 元素添加监听器。事实上，你只需要在该元素初始渲染的时候添加监听器即可。</div><div class="notion-text notion-block-f402c13a3c96412b89b0cc2a44385785">当你使用 <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes">ES6 class (opens new window)</a>语法定义一个组件的时候，通常的做法是将事件处理函数声明为 class 中的方法。例如，下面的 <code class="notion-inline-code">Toggle</code> 组件会渲染一个让用户切换开关状态的按钮：</div><div class="notion-text notion-block-b1fad27b16564ba68f512a0799b6dd30">你必须谨慎对待 JSX 回调函数中的 <code class="notion-inline-code">this</code>，在 JavaScript 中，class 的方法默认不会<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind">绑定 (opens new window)</a><code class="notion-inline-code">this</code>。如果你忘记绑定 <code class="notion-inline-code">this.handleClick</code> 并把它传入了 <code class="notion-inline-code">onClick</code>，当你调用这个函数的时候 <code class="notion-inline-code">this</code> 的值为 <code class="notion-inline-code">undefined</code>。</div><div class="notion-text notion-block-c684e21e9b4c41088e9290bf23b5f705">这并不是 React 特有的行为；这其实与 <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/">JavaScript 函数工作原理 (opens new window)</a>有关。通常情况下，如果你没有在方法后面添加 <code class="notion-inline-code">()</code>，例如 <code class="notion-inline-code">onClick={this.handleClick}</code>，你应该<b>为这个方法绑定 </b><code class="notion-inline-code"><b>this</b></code>。</div><div class="notion-text notion-block-5d7fd525402d4e168e983a100c292849">如果觉得使用 <code class="notion-inline-code">bind</code> 很麻烦，这里有两种方式可以解决。如果你正在使用实验性的 <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://babeljs.io/docs/plugins/transform-class-properties/">public class fields 语法 (opens new window)</a>，你可以使用 class fields 正确的绑定回调函数：</div><div class="notion-text notion-block-695c0c6d59214eccac49955bad191290"><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://github.com/facebookincubator/create-react-app">Create React App (opens new window)</a>默认启用此语法。</div><div class="notion-text notion-block-66ff397fd2764a0fb9cd44873aeaf8e5">如果你没有使用 class fields 语法，你可以在回调中使用<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions">箭头函数 (opens new window)</a>：</div><div class="notion-text notion-block-8774a82520a24b14b44424c19e36c238">此语法问题在于每次渲染 <code class="notion-inline-code">LoggingButton</code> 时都会创建不同的回调函数。在大多数情况下，这没什么问题，但如果该回调函数作为 prop 传入子组件时，这些组件可能会进行额外的重新渲染。<b>我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题</b>。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-5122f5c787614e5c984a0b7c14e7dcae" data-id="5122f5c787614e5c984a0b7c14e7dcae"><span><div id="5122f5c787614e5c984a0b7c14e7dcae" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5122f5c787614e5c984a0b7c14e7dcae" title="事件命名规范"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>事件命名规范</b></span></span></h4><div class="notion-text notion-block-d249defb8f454ebdb333438157df0262">在 React 中，有一个命名规范，通常会将代表事件的监听 prop 命名为 <code class="notion-inline-code">on[Event]</code>，将处理事件的监听方法命名为 <code class="notion-inline-code">handle[Event]</code> 这样的格式。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7f46973167c64489862e864dcb940fb3" data-id="7f46973167c64489862e864dcb940fb3"><span><div id="7f46973167c64489862e864dcb940fb3" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7f46973167c64489862e864dcb940fb3" title="向事件处理程序传递参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>向事件处理程序传递参数</b></span></span></h4><div class="notion-text notion-block-2fb1cfff1597405da3acdf161ad60641">在循环中，通常我们会为事件处理函数传递额外的参数。例如，若 <code class="notion-inline-code">id</code> 是你要删除那一行的 ID，以下两种方式都可以向事件处理函数传递参数：</div><div class="notion-text notion-block-62c6d3876a064b378fcd44da8bf89d1d">上述两种方式是等价的，分别通过<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">箭头函数 (opens new window)</a>和 <code class="notion-inline-code"><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind">Function.prototype.bind</a></code><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind"> (opens new window)</a>来实现。</div><div class="notion-text notion-block-433f858e82134016a8adadf11bcdac83">在这两种情况下，<b>React 的事件对象 </b><code class="notion-inline-code"><b>e</b></code><b> 会被作为第二个参数传递</b>。如果通过箭头函数的方式，事件对象必须显式的进行传递，而通过 <code class="notion-inline-code">bind</code> 的方式，事件对象以及更多的参数将会被隐式的进行传递。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-d5463f3aa5ad4b66bb224b50c30c9c2b" data-id="d5463f3aa5ad4b66bb224b50c30c9c2b"><span><div id="d5463f3aa5ad4b66bb224b50c30c9c2b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d5463f3aa5ad4b66bb224b50c30c9c2b" title="条件渲染"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>条件渲染</b></span></span></h3><div class="notion-text notion-block-79516489175943ab9427646678538910">React 中的条件渲染和 JavaScript 中的一样，使用 JavaScript 运算符 <code class="notion-inline-code"><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else">if</a></code><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else"> (opens new window)</a>或者<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">条件运算符 (opens new window)</a>去创建元素来表现当前的状态，然后让 React 根据它们来更新 UI。</div><div class="notion-text notion-block-08103e6b0757468598329d39543af069">观察这两个组件:</div><div class="notion-text notion-block-3bc7bc8d02ca4a1e8263d8331726e7b8">再创建一个 <code class="notion-inline-code">Greeting</code> 组件，它会根据用户是否登录来决定显示上面的哪一个组件。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1ae9e403a59a46309c7e35ceba5b1557" data-id="1ae9e403a59a46309c7e35ceba5b1557"><span><div id="1ae9e403a59a46309c7e35ceba5b1557" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1ae9e403a59a46309c7e35ceba5b1557" title="元素变量"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>元素变量</b></span></span></h4><div class="notion-text notion-block-5244841052314e1aba83af9d358e092f">你可以使用变量来储存元素。 它可以帮助你有条件地渲染组件的一部分，而其他的渲染部分并不会因此而改变。</div><div class="notion-text notion-block-0c8a20a0f0314985aed2d4d3cc17c2cc"><b><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://codepen.io/gaearon/pen/QKzAgB?editors=0010">在 CodePen 上尝试</a></b><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://codepen.io/gaearon/pen/QKzAgB?editors=0010">(opens new window)</a></div><blockquote class="notion-quote notion-block-a35e1c5f166245eda8a0a1d414b3f6ff"><div>此方式有些复杂~</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7a17f423db6049798bfa8d235f079056" data-id="7a17f423db6049798bfa8d235f079056"><span><div id="7a17f423db6049798bfa8d235f079056" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7a17f423db6049798bfa8d235f079056" title="与运算符 &amp;&amp;"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>与运算符 &amp;&amp;</b></span></span></h4><div class="notion-text notion-block-32ed61443fc14714a7f7642931789f24">通过花括号包裹代码，你可以<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/introducing-jsx.html#embedding-expressions-in-jsx">在 JSX 中嵌入表达式 (opens new window)</a>。这也包括 JavaScript 中的逻辑与 (&amp;&amp;) 运算符。它可以很方便地进行元素的条件渲染：</div><div class="notion-text notion-block-c514a599b73349218806551cc9c7c5c2">如果条件是 <code class="notion-inline-code">true</code>，<code class="notion-inline-code">&amp;&amp;</code> 右侧的元素就会被渲染，如果是 <code class="notion-inline-code">false</code>，React 会忽略并跳过它。</div><div class="notion-text notion-block-4e843046db3c41fcacc0c3add498a226">请<b>注意</b>，返回 false 的表达式会使 <code class="notion-inline-code">&amp;&amp;</code> 后面的元素被跳过，但会返回 false 表达式。在下面示例中，render 方法的返回值是 <code class="notion-inline-code">&lt;div&gt;0&lt;/div&gt;</code>。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-8a775059744446d989a86d2736b3f034" data-id="8a775059744446d989a86d2736b3f034"><span><div id="8a775059744446d989a86d2736b3f034" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8a775059744446d989a86d2736b3f034" title="三目运算符"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>三目运算符</b></span></span></h4><blockquote class="notion-quote notion-block-029da04ce2f243a38eb243bcaf19e3c5"><div>可通过三目运算符来条件渲染相应组件。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-3bfdfae250754805b5b9b3ba6a28d95f" data-id="3bfdfae250754805b5b9b3ba6a28d95f"><span><div id="3bfdfae250754805b5b9b3ba6a28d95f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3bfdfae250754805b5b9b3ba6a28d95f" title="阻止组件渲染"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>阻止组件渲染</b></span></span></h4><div class="notion-text notion-block-7576acad12524634a1ade75184e7ecca">通过让 <code class="notion-inline-code">render</code> 方法直接返回 <code class="notion-inline-code">null</code>阻止渲染：</div><div class="notion-text notion-block-9a366fdac9034c6abe7f75138a0cffbf">在组件的 <code class="notion-inline-code">render</code> 方法中返回 <code class="notion-inline-code">null</code> 并不会影响组件的生命周期。例如，上面这个示例中，<code class="notion-inline-code">componentDidUpdate</code> 依然会被调用。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-23b3c7bd60cf49ca8c4ab0f02d521c80" data-id="23b3c7bd60cf49ca8c4ab0f02d521c80"><span><div id="23b3c7bd60cf49ca8c4ab0f02d521c80" class="notion-header-anchor"></div><a class="notion-hash-link" href="#23b3c7bd60cf49ca8c4ab0f02d521c80" title="列表&amp;Key"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>列表&amp;Key</b></span></span></h3><div class="notion-text notion-block-2beae92cfe634ccb8e16130d4963e2d6">如下代码，我们使用 <code class="notion-inline-code"><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map()</a></code><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"> (opens new window)</a>函数让数组中的每一项变双倍，然后我们得到了一个新的列表 <code class="notion-inline-code">doubled</code> 并打印出来：</div><div class="notion-text notion-block-1523610820df4957b1f876c66ed12758">在 React 中，把数组转化为<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/rendering-elements.html">元素 (opens new window)</a>列表的过程是相似的。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ca38efca406948fca558fe4b0acc4be5" data-id="ca38efca406948fca558fe4b0acc4be5"><span><div id="ca38efca406948fca558fe4b0acc4be5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ca38efca406948fca558fe4b0acc4be5" title="渲染多个组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>渲染多个组件</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1544822bd52c4513bdd71ab34b8c061d" data-id="1544822bd52c4513bdd71ab34b8c061d"><span><div id="1544822bd52c4513bdd71ab34b8c061d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1544822bd52c4513bdd71ab34b8c061d" title="基础列表组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>基础列表组件</b></span></span></h4><div class="notion-text notion-block-f1c76ee0ce57414b8c2f80ef27fdb39d">将列表组合成一个组件：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7ca4d114c7b1416ab911ca1cbad235f0" data-id="7ca4d114c7b1416ab911ca1cbad235f0"><span><div id="7ca4d114c7b1416ab911ca1cbad235f0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7ca4d114c7b1416ab911ca1cbad235f0" title="key"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>key</b></span></span></h4><div class="notion-text notion-block-3245df0a979e47e193b6a2c54956c9d7"><b>key 帮助 React 识别哪些元素改变了</b>，比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。</div><div class="notion-text notion-block-86d5071624ce4e858f2c7d3838d0ebaa">一个元素的 key 最好是这个元素在列表中拥有的<b>一个独一无二的字符串</b>。<b>通常，我们使用数据中的 id 来作为元素的 key</b></div><div class="notion-text notion-block-9c3e44bb4ab54ee9ab89150699ebbcf9">当元素没有确定 id 的时候，<b>万不得已你可以使用元素索引 index 作为 key</b>：</div><div class="notion-text notion-block-3decc36fe4f0438e96d8d82d89127303"><b>如果列表项目的顺序可能会变化，我们不建议使用索引来用作 key 值，因为这样做会导致性能变差，还可能引起组件状态的问题。</b></div><div class="notion-text notion-block-8599cb527bd348219003d04dc9ca6608">如果你选择不指定显式的 key 值，那么 React 将默认使用索引用作为列表项目的 key 值</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-4ad668008d7b4f63ac215d5fdfb1cb50" data-id="4ad668008d7b4f63ac215d5fdfb1cb50"><span><div id="4ad668008d7b4f63ac215d5fdfb1cb50" class="notion-header-anchor"></div><a class="notion-hash-link" href="#4ad668008d7b4f63ac215d5fdfb1cb50" title="用 key 提取组件 (在map方法内设置key)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>用 key 提取组件 (在map方法内设置key)</b></span></span></h4><div class="notion-text notion-block-3be2229d3f9f4847b2445fe75245ca36">元素的 key 只有放在就近的数组上下文中才有意义。</div><div class="notion-text notion-block-b607f1b0f6d549e19062d6f3984e898e"><b>例子：不正确的使用 key 的方式</b></div><div class="notion-text notion-block-97c1015659f843fa92b9740d07bd0887">一个好的经验法则是：<b>在 </b><code class="notion-inline-code"><b>map()</b></code><b> 方法中的元素需要设置 key 属性</b>。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-c242843d2c1047a89ddbda19d599147a" data-id="c242843d2c1047a89ddbda19d599147a"><span><div id="c242843d2c1047a89ddbda19d599147a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c242843d2c1047a89ddbda19d599147a" title="key 只是在兄弟节点之间必须唯一"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>key 只是在兄弟节点之间必须唯一</b></span></span></h4><div class="notion-text notion-block-71c0fc7eb0b84ee198e03118b02624a9">数组元素中使用的 key 在其兄弟节点之间应该是独一无二的。然而，它们<b>不需要是全局唯一的</b>。当我们生成两个不同的数组时，我们可以使用相同的 key 值。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-772c39b0ffc14349b3af25c757cade07" data-id="772c39b0ffc14349b3af25c757cade07"><span><div id="772c39b0ffc14349b3af25c757cade07" class="notion-header-anchor"></div><a class="notion-hash-link" href="#772c39b0ffc14349b3af25c757cade07" title="不能用key当props名传给子组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>不能用</b><code class="notion-inline-code"><b>key</b></code><b>当props名传给子组件</b></span></span></h4><div class="notion-text notion-block-09499874f2824425a88ca14b2a7244d1">key 会传递信息给 React ，但不会传递给你的组件。如果你的组件中需要使用 <code class="notion-inline-code">key</code> 属性的值，请用其他属性名显式传递这个值：</div><div class="notion-text notion-block-88cd094c254446cba40e3c833bc800e9">上面例子中，<code class="notion-inline-code">Post</code> 组件可以读出 <code class="notion-inline-code">props.id</code>，但是<b>不能读出 </b><code class="notion-inline-code"><b>props.key</b></code>。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-aaa098a6cd1f426f9d0d762ca6eef96d" data-id="aaa098a6cd1f426f9d0d762ca6eef96d"><span><div id="aaa098a6cd1f426f9d0d762ca6eef96d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#aaa098a6cd1f426f9d0d762ca6eef96d" title="在 JSX 中嵌入 map()"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>在 JSX 中嵌入 map()</b></span></span></h4><div class="notion-text notion-block-b29a7904e32541bd842f17c62ff7fbdd">JSX 允许在大括号中<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/introducing-jsx.html#embedding-expressions-in-jsx">嵌入任何表达式 (opens new window)</a>，所以我们可以内联 <code class="notion-inline-code">map()</code> 返回的结果：</div><div class="notion-text notion-block-a1cf812a4bdf49d38005986a485f2a1f">这么做有时可以使你的代码更清晰，但有时这种风格也会被滥用。</div><div class="notion-text notion-block-1e5a6139aaff4e139e9f843a850c59da">就像在 JavaScript 中一样，何时需要为了可读性提取出一个变量，这完全取决于你。但请记住，如果一个 <code class="notion-inline-code">map()</code> 嵌套了太多层级，那可能就是你<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/components-and-props.html#extracting-components">提取组件 (opens new window)</a>的一个好时机。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-47eb2096869843f8992a44374d35f6eb" data-id="47eb2096869843f8992a44374d35f6eb"><span><div id="47eb2096869843f8992a44374d35f6eb" class="notion-header-anchor"></div><a class="notion-hash-link" href="#47eb2096869843f8992a44374d35f6eb" title="表单"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>表单</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-c9e989ace2a04313a78840aa20c5e3b5" data-id="c9e989ace2a04313a78840aa20c5e3b5"><span><div id="c9e989ace2a04313a78840aa20c5e3b5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c9e989ace2a04313a78840aa20c5e3b5" title="受控组件（双向数据绑定）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>受控组件（双向数据绑定）</b></span></span></h4><div class="notion-text notion-block-f1a5fdbe32854e4d806f25e369e46766">在 HTML 中，表单元素（如<code class="notion-inline-code">&lt;input&gt;</code>、 <code class="notion-inline-code">&lt;textarea&gt;</code> 和 <code class="notion-inline-code">&lt;select&gt;</code>）通常自己维护 state，并根据用户输入进行更新。而在 React 中，可变状态（mutable state）通常保存在组件的 state 属性中，并且只能通过使用 <code class="notion-inline-code"><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/react-component.html#setstate">setState()</a></code><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/react-component.html#setstate"> (opens new window)</a>来更新。</div><div class="notion-text notion-block-14d434c9be434b55bb1040f952509b56">我们可以把两者结合起来，使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。</div><div class="notion-text notion-block-4ad80c271a0a4fa69ba9ddc79cf6d3a8">例如，如果我们想让前一个示例在提交时打印出名称，我们可以将表单写为受控组件：</div><blockquote class="notion-quote notion-block-751836758a064ed8a4cd72bd6868391a"><div>类似于vue中的双向绑定，v-model</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ea351807b75c40db84a0834e0b71a682" data-id="ea351807b75c40db84a0834e0b71a682"><span><div id="ea351807b75c40db84a0834e0b71a682" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ea351807b75c40db84a0834e0b71a682" title="textarea 标签（使用value定义值）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>textarea 标签（使用value定义值）</b></span></span></h4><div class="notion-text notion-block-6b636222586b4e6fbd8a24216881e038">在 HTML 中, <code class="notion-inline-code">&lt;textarea&gt;</code> 元素通过其子元素定义其文本:</div><div class="notion-text notion-block-79355ff227b74b24894bebd248d35d9c"><b>在 React 中，</b><code class="notion-inline-code"><b>&lt;textarea&gt;</b></code><b> 使用 </b><code class="notion-inline-code"><b>value</b></code><b> 属性赋值</b>。这样，可以使得使用 <code class="notion-inline-code">&lt;textarea&gt;</code> 的表单和使用单行 input 的表单非常类似：</div><div class="notion-text notion-block-5bf0602fbe7c4dc2ad53682a198ed476"><b>注意，</b><code class="notion-inline-code"><b>this.state.value</b></code><b> 初始化于构造函数中，因此文本区域默认有初值</b></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e9f521019159417cb724b19db97be133" data-id="e9f521019159417cb724b19db97be133"><span><div id="e9f521019159417cb724b19db97be133" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e9f521019159417cb724b19db97be133" title="select 标签 （value代替选中属性）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>select 标签 （value代替选中属性）</b></span></span></h4><div class="notion-text notion-block-6824be092378420883b0c10d48895751"><b>React 在根 </b><code class="notion-inline-code"><b>select</b></code><b> 标签上使用 </b><code class="notion-inline-code"><b>value</b></code><b> 属性代替</b><code class="notion-inline-code"><b>option</b></code><b>元素上的</b><code class="notion-inline-code"><b>selected</b></code><b> 属性（选中属性）</b></div><div class="notion-text notion-block-5e8fe385c7be4d5c92607c6ea870f053">在 HTML 中，<code class="notion-inline-code">&lt;select&gt;</code> 创建下拉列表标签。例如，如下 HTML 创建了水果相关的下拉列表：</div><div class="notion-text notion-block-36fbe1cf57b74bbf890f1353e941fc0b">请注意，由于 <code class="notion-inline-code">selected</code> 属性的缘故，椰子选项默认被选中。<b>React 并不会使用 </b><code class="notion-inline-code"><b>selected</b></code><b> 属性，而是在根 </b><code class="notion-inline-code"><b>select</b></code><b> 标签上使用 </b><code class="notion-inline-code"><b>value</b></code><b> 属性</b>。这在受控组件中更便捷，因为您只需要在根标签中更新它。例如：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2b49a47da9424b9cb549bd679f4c61b0" data-id="2b49a47da9424b9cb549bd679f4c61b0"><span><div id="2b49a47da9424b9cb549bd679f4c61b0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2b49a47da9424b9cb549bd679f4c61b0" title="select多选"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>select多选</b></span></span></h4><div class="notion-text notion-block-ae90ab8d57ef4e21a59a1839b10b691b">你可以将数组传递到 <code class="notion-inline-code">value</code> 属性中，以支持在 <code class="notion-inline-code">select</code> 标签中选择多个选项：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-571b25ba938345989708e609d266e6f9" data-id="571b25ba938345989708e609d266e6f9"><span><div id="571b25ba938345989708e609d266e6f9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#571b25ba938345989708e609d266e6f9" title="小总结"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>小总结</b></span></span></h4><div class="notion-text notion-block-9ddbc0932b364823b1d1c38e3b28405f">总的来说，这使得 <code class="notion-inline-code">&lt;input type=&quot;text&quot;&gt;</code>, <code class="notion-inline-code">&lt;textarea&gt;</code> 和 <code class="notion-inline-code">&lt;select&gt;</code> 之类的标签都非常相似—它们都接受一个 <code class="notion-inline-code">value</code> 属性，你可以使用它来实现受控组件。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2e778cbb4dba4349b7db70cf85c8fe76" data-id="2e778cbb4dba4349b7db70cf85c8fe76"><span><div id="2e778cbb4dba4349b7db70cf85c8fe76" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2e778cbb4dba4349b7db70cf85c8fe76" title="文件 input 标签 （非受控组件）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>文件 input 标签 （非受控组件）</b></span></span></h4><div class="notion-text notion-block-ea25c3c6e8e445f7a478e2b355668af5">在 HTML 中，<code class="notion-inline-code">&lt;input type=&quot;file&quot;&gt;</code> 允许用户从存储设备中选择一个或多个文件，将其上传到服务器，或通过使用 JavaScript 的 <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications">File API (opens new window)</a>进行控制。</div><div class="notion-text notion-block-54e3650a7f424ecb97ddfbbc3a2b8fe6">因为它的 value 只读，所以它是 React 中的一个<b>非受控</b>组件。将与其他非受控组件<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/uncontrolled-components.html#the-file-input-tag">在后续文档中 (opens new window)</a>一起讨论。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-378ed774aa3d4c03812d518d7d8b74e7" data-id="378ed774aa3d4c03812d518d7d8b74e7"><span><div id="378ed774aa3d4c03812d518d7d8b74e7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#378ed774aa3d4c03812d518d7d8b74e7" title="处理多个输入"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>处理多个输入</b></span></span></h4><div class="notion-text notion-block-c68968e7a4b74eb0bfbcdf3148310cb0">当需要处理多个 <code class="notion-inline-code">input</code> 元素时，我们可以给每个元素添加 <code class="notion-inline-code">name</code> 属性，并让处理函数根据 <code class="notion-inline-code">event.target.name</code> 的值选择要执行的操作。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-074c9b812a8e4102be29e2b55e65e85b" data-id="074c9b812a8e4102be29e2b55e65e85b"><span><div id="074c9b812a8e4102be29e2b55e65e85b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#074c9b812a8e4102be29e2b55e65e85b" title="受控输入空值"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>受控输入空值</b></span></span></h4><div class="notion-text notion-block-2dcb554b75754e1582a6187fc20fd514">在<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/forms.html#controlled-components">受控组件 (opens new window)</a>上指定 value 的 prop 会阻止用户更改输入。如果你指定了 <code class="notion-inline-code">value</code>，但输入仍可编辑，则可能是你意外地将<code class="notion-inline-code">value</code> 设置为 <code class="notion-inline-code">undefined</code> 或 <code class="notion-inline-code">null</code>。</div><div class="notion-text notion-block-3142ea5b853c436b90992985cc6ade4d">下面的代码演示了这一点。（输入最初被锁定，但在短时间延迟后变为可编辑。）</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-0c4d84ad6dfa4e48baa45596158e87d4" data-id="0c4d84ad6dfa4e48baa45596158e87d4"><span><div id="0c4d84ad6dfa4e48baa45596158e87d4" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0c4d84ad6dfa4e48baa45596158e87d4" title="受控组件的替代品 (非受控组件)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>受控组件的替代品 (非受控组件)</b></span></span></h4><div class="notion-text notion-block-9690f1abd9114c8b8a8f62c0441977d6">有时使用受控组件会很麻烦，因为<b>你需要为数据变化的每种方式都编写事件处理函数，并通过一个 React 组件传递所有的输入 state</b>。当你将之前的代码库转换为 React 或将 React 应用程序与非 React 库集成时，这可能会令人厌烦。在这些情况下，你可能希望使用<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/uncontrolled-components.html">非受控组件 (opens new window)</a>, 这是实现输入表单的另一种方式。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-a024ae2311ce44be8fc600407cde4cee" data-id="a024ae2311ce44be8fc600407cde4cee"><span><div id="a024ae2311ce44be8fc600407cde4cee" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a024ae2311ce44be8fc600407cde4cee" title="成熟的解决方案"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>成熟的解决方案</b></span></span></h4><div class="notion-text notion-block-9be8c684c6574638a812f392434a392a">如果你想寻找包含验证、追踪访问字段以及处理表单提交的完整解决方案，使用 <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://jaredpalmer.com/formik">Formik (opens new window)</a>是不错的选择。然而，它也是建立在受控组件和管理 state 的基础之上 —— 所以不要忽视学习它们。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-59c8419f13db429ca4fe6c9bb50c9625" data-id="59c8419f13db429ca4fe6c9bb50c9625"><span><div id="59c8419f13db429ca4fe6c9bb50c9625" class="notion-header-anchor"></div><a class="notion-hash-link" href="#59c8419f13db429ca4fe6c9bb50c9625" title="状态提升 (共享状态)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>状态提升 (共享状态)</b></span></span></h3><div class="notion-text notion-block-0b58cf88fddb4a54b9d558277ce2e107">通常，<b>多个组件需要反映相同的变化数据，这时我们建议将共享状态提升到最近的共同父组件中去</b>。</div><div class="notion-text notion-block-253fd58bc82b4bbdab508b501150dd6f">在 React 中，<b>将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中，便可实现共享 state。这就是所谓的“状态提升”</b></div><div class="notion-text notion-block-3b2948fa18404a918c255ea62a86e630">两个输入框共享数据的例子：</div><div class="notion-text notion-block-6af06e1b64c84c83828a3e1bce47611e"><b><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://codepen.io/gaearon/pen/WZpxpz?editors=0010">在 CodePen 上尝试</a></b><a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://codepen.io/gaearon/pen/WZpxpz?editors=0010">(opens new window)</a></div><div class="notion-text notion-block-1d3d8a7396404cd0821da6b848cd92b9">笔记</div><ol start="1" class="notion-list notion-list-numbered notion-block-90df81a4a08a47f383b84e640a6c3d84"><li>父组件给所有子组件传入state的值</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-8f72ea70aeb941fdbb133b6b281f0163"><li>子组件修改值时调用父组件的方法并把值传出</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-7edebd88e78c4a129b168ccc36a4e76a"><li>父组件接收到值之后修改state</li></ol><ol start="4" class="notion-list notion-list-numbered notion-block-befc145b395f4064a847ffb13fc3cb07"><li>state被修改之后重新执行render函数，并回到第1步</li></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7d192e470f5c4247bfffb7facf6b7a1b" data-id="7d192e470f5c4247bfffb7facf6b7a1b"><span><div id="7d192e470f5c4247bfffb7facf6b7a1b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7d192e470f5c4247bfffb7facf6b7a1b" title="小结"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>小结</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-45ceed79d3824c2089ff82faf2c0e905"><li>任何可变数据应当只有一个相对应的唯一“数据源”</li><ul class="notion-list notion-list-disc notion-block-45ceed79d3824c2089ff82faf2c0e905"><li>通常，state 都是首先添加到需要渲染数据的组件中去</li><li>然后，如果其他组件也需要这个 state，那么你可以将它提升至这些组件的最近共同父组件中</li><li>你应当依靠<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://zh-hans.reactjs.org/docs/state-and-lifecycle.html#the-data-flows-down">自上而下的数据流 (opens new window)</a>，而不是尝试在不同组件间同步 state。</li></ul></ul><ul class="notion-list notion-list-disc notion-block-7c58ca78594f4aefaff6ca94384a889c"><li>“存在”于组件中的任何 state，仅有组件自己能够修改它</li></ul><ul class="notion-list notion-list-disc notion-block-25f8f9ca7bc84b6aab16ffc78e6dea91"><li>如果某些数据可以由 props 或 state 推导得出，那么它就不应该存在于 state 中。（如上例中，经过tryConvert方法转换的后的值。）</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-a61b4bceda064fdbbc6b849137d293ea" data-id="a61b4bceda064fdbbc6b849137d293ea"><span><div id="a61b4bceda064fdbbc6b849137d293ea" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a61b4bceda064fdbbc6b849137d293ea" title="React开发者工具（debug）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>React开发者工具（debug）</b></span></span></h4><div class="notion-text notion-block-0e910db42e354a6a8844c998441a5775">当你在 UI 中发现错误时，可以使用 <a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://github.com/facebook/react/tree/master/packages/react-devtools">React 开发者工具 (opens new window)</a>来检查问题组件的 props，并且按照组件树结构逐级向上搜寻，直到定位到负责更新 state 的那个组件。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-da1bf02ccaa94923949bd0fb4e025e4d" data-id="da1bf02ccaa94923949bd0fb4e025e4d"><span><div id="da1bf02ccaa94923949bd0fb4e025e4d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#da1bf02ccaa94923949bd0fb4e025e4d" title="组合vs继承"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>组合vs继承</b></span></span></h3><div class="notion-text notion-block-278db91c907e4f76987b07606b017a81">React 有十分强大的组合模式。我们<b>推荐使用组合而非继承来实现组件间的代码重用</b>。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-b3a233dba7d54f4b9d343218e07d8508" data-id="b3a233dba7d54f4b9d343218e07d8508"><span><div id="b3a233dba7d54f4b9d343218e07d8508" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b3a233dba7d54f4b9d343218e07d8508" title="包含关系 (组件组合)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>包含关系 (组件组合)</b></span></span></h4><div class="notion-text notion-block-55261b6619de4c40974224ca098419b5">有些组件无法提前知晓它们子组件的具体内容。在 <code class="notion-inline-code">Sidebar</code>（侧边栏）和 <code class="notion-inline-code">Dialog</code>（对话框）等展现通用容器（box）的组件中特别容易遇到这种情况。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-31d274a25ea74a4bb527213f45d098ba" data-id="31d274a25ea74a4bb527213f45d098ba"><span><div id="31d274a25ea74a4bb527213f45d098ba" class="notion-header-anchor"></div><a class="notion-hash-link" href="#31d274a25ea74a4bb527213f45d098ba" title="props的children属性（类似vue的插槽）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>props的children属性（类似vue的插槽）</b></span></span></h4><div class="notion-text notion-block-9c9effe8445a4d02b3327198908e7e9f">我们建议这些组件使用一个<b>特殊的 </b><code class="notion-inline-code"><b>children</b></code><b> prop 来将他们的子组件传递到渲染结果中</b>：</div><div class="notion-text notion-block-eb717c9e12b442b88c7a11b7c9db84c2">笔记</div><div class="notion-text notion-block-9a5e9e361b1246918808f542deb083f6">类似于vue中的插槽</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-0722ffc0ba78439599921581f3712a57" data-id="0722ffc0ba78439599921581f3712a57"><span><div id="0722ffc0ba78439599921581f3712a57" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0722ffc0ba78439599921581f3712a57" title="props传入组件（类似vue命名插槽）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>props传入组件（类似vue命名插槽）</b></span></span></h4><div class="notion-text notion-block-e98769113c3d42109645aa0bcf90cfa0">少数情况下，你可能需要在一个组件中预留出几个“洞”。这种情况下，我们可以不使用 <code class="notion-inline-code">children</code>，而是自行约定：将所需内容传入 props，并使用相应的 prop。</div><div class="notion-text notion-block-ad9a8226a04a447ab0f2ea42ae0b6702"><code class="notion-inline-code">&lt;Contacts /&gt;</code> 和 <code class="notion-inline-code">&lt;Chat /&gt;</code> 之类的 React 元素本质就是对象（object），所以你可以把它们当作 props，像其他数据一样传递。<b>你可以将任何格式的数据作为 props 进行传递。</b></div><div class="notion-text notion-block-9ab2c972e6c04450b44eb05bd5b07727">笔记</div><div class="notion-text notion-block-e29c8272ed0d41ccae2a60e739d5ef32">类似于vue中的命名插槽</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-0a3ed0af40f94d1886f07ff59730d7d9" data-id="0a3ed0af40f94d1886f07ff59730d7d9"><span><div id="0a3ed0af40f94d1886f07ff59730d7d9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0a3ed0af40f94d1886f07ff59730d7d9" title="特例关系（字符串与组件组合）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>特例关系（字符串与组件组合）</b></span></span></h4><div class="notion-text notion-block-24a594d006b04e4aba362c0e23dfd402">有些时候，我们会把一些组件看作是其他组件的特殊实例，比如 <code class="notion-inline-code">WelcomeDialog</code> 可以说是 <code class="notion-inline-code">Dialog</code> 的特殊实例。</div><div class="notion-text notion-block-e8b0adca2c2949ed9b5579addb3103e1">在 React 中，我们也可以通过组合来实现这一点。“特殊”组件可以通过 props 定制并渲染“一般”组件：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-518eae0a5e08416c89f4ac380e69ea61" data-id="518eae0a5e08416c89f4ac380e69ea61"><span><div id="518eae0a5e08416c89f4ac380e69ea61" class="notion-header-anchor"></div><a class="notion-hash-link" href="#518eae0a5e08416c89f4ac380e69ea61" title="class方式的组件组合"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>class方式的组件组合</b></span></span></h4><div class="notion-text notion-block-468d66be5f7e42538a877bff2f75b6cf">组合也同样适用于以 class 形式定义的组件。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-13ffc33701904b54a0d309eb5035f856" data-id="13ffc33701904b54a0d309eb5035f856"><span><div id="13ffc33701904b54a0d309eb5035f856" class="notion-header-anchor"></div><a class="notion-hash-link" href="#13ffc33701904b54a0d309eb5035f856" title="那么继承呢？（不推荐）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>那么继承呢？（不推荐）</b></span></span></h4><div class="notion-text notion-block-bc188546ede4451596ec804811712382">在 Facebook，我们在成百上千个组件中使用 React。我们并没有发现需要使用继承来构建组件层次的情况。</div><div class="notion-text notion-block-5ccbddaf732d4aab987d46d01044a8e4">Props 和组合为你提供了清晰而安全地定制组件外观和行为的灵活方式。<b>注意：组件可以接受任意 props，包括基本数据类型，React 元素以及函数</b>。</div><div class="notion-text notion-block-6dae309ef8ae486683895a2872f324b6">如果你想要在组件间复用非 UI 的功能，我们建议将其提取为一个单独的 JavaScript 模块，如函数、对象或者类。组件可以直接引入（import）而<b>无需通过 extend 继承它们</b>。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-aa9b686b4baf40398afcfab98484a811" data-id="aa9b686b4baf40398afcfab98484a811"><span><div id="aa9b686b4baf40398afcfab98484a811" class="notion-header-anchor"></div><a class="notion-hash-link" href="#aa9b686b4baf40398afcfab98484a811" title="React哲学"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>React哲学</b></span></span></h3><div class="notion-text notion-block-820e26564e4440679cb1e7661665fd4e">React 最棒的部分之一是引导我们思考如何构建一个应用。在这篇文档中，我们将会通过 React 构建一个可搜索的产品数据表格来更深刻地领会 React 哲学。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7a363a23c93f425b84e3d6e366903fb3" data-id="7a363a23c93f425b84e3d6e366903fb3"><span><div id="7a363a23c93f425b84e3d6e366903fb3" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7a363a23c93f425b84e3d6e366903fb3" title="从设计稿开始"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>从设计稿开始</b></span></span></h4><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-5bd4b4a5a3d5420c871f61f890c70bad"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:288px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://zh-hans.reactjs.org/static/1071fbcc9eed01fddc115b41e193ec11/d4770/thinking-in-react-mock.png?t=5bd4b4a5-a3d5-420c-871f-61f890c70bad" alt="notion image" loading="lazy" decoding="async"/></div></figure><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-36954106376a4f259e6a98aa57f4bf61" data-id="36954106376a4f259e6a98aa57f4bf61"><span><div id="36954106376a4f259e6a98aa57f4bf61" class="notion-header-anchor"></div><a class="notion-hash-link" href="#36954106376a4f259e6a98aa57f4bf61" title="第一步：将设计好的 UI 划分为组件层级"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>第一步：将设计好的 UI 划分为组件层级</b></span></span></h4><div class="notion-text notion-block-ab8afea433e846308f420f0a8b3b4694"><b>首先，你需要在设计稿上用方框圈出每一个组件（包括它们的子组件）</b></div><div class="notion-text notion-block-3c3bad9c2c5e4539b23ef6cc514e1550">你会看到我们的应用中包含五个组件。我们已经将每个组件展示的数据标注为了斜体。</div><ol start="1" class="notion-list notion-list-numbered notion-block-3b69b59f79174c5aa3f6b5bfa01faab0"><li><code class="notion-inline-code"><b>FilterableProductTable</b></code><b> (橙色):</b> 是整个示例应用的整体</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-520b291c4d204296ba6c4fbbf3fb7455"><li><code class="notion-inline-code"><b>SearchBar</b></code><b> (蓝色):</b> 接受所有的<em>用户输入</em></li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-e1e21580691245c4a637c569efdec073"><li><code class="notion-inline-code"><b>ProductTable</b></code><b> (绿色):</b> 展示<em>数据内容</em>并根据<em>用户输入</em>筛选结果</li></ol><ol start="4" class="notion-list notion-list-numbered notion-block-d1406db6041141b08fe3b5ae045a57fd"><li><code class="notion-inline-code"><b>ProductCategoryRow</b></code><b> (天蓝色):</b> 为每一个<em>产品类别</em>展示标题</li></ol><ol start="5" class="notion-list notion-list-numbered notion-block-1a23da8d8318409599fb0870403a7097"><li><code class="notion-inline-code"><b>ProductRow</b></code><b> (红色):</b> 每一行展示一个<em>产品</em></li></ol><div class="notion-text notion-block-6a20991c10174bd089e35f092b3a6ad6">你可能注意到，<code class="notion-inline-code">ProductTable</code> 的表头（包含 “Name” 和 “Price” 的那一部分）并未单独成为一个组件。这仅仅是一种偏好选择，如何处理这一问题也一直存在争论。（简单的可以不用单独分一个组件，复杂的作为一个独立的组件就有必要了）</div><div class="notion-text notion-block-1a1a660598a84eb395cd7633b7bac91c">组件层级：</div><ul class="notion-list notion-list-disc notion-block-afaab39557584ac0839e0c6e13e337e8"><li><code class="notion-inline-code">FilterableProductTable</code></li><ul class="notion-list notion-list-disc notion-block-afaab39557584ac0839e0c6e13e337e8"><li><code class="notion-inline-code">SearchBar</code></li><li><code class="notion-inline-code">ProductTable</code></li><ul class="notion-list notion-list-disc notion-block-2881d54e6a514b4e9dc4000df5e80736"><li><code class="notion-inline-code">ProductCategoryRow</code></li><li><code class="notion-inline-code">ProductRow</code></li></ul></ul></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ed59dfab4b534403a74a1bc40b7b98ac" data-id="ed59dfab4b534403a74a1bc40b7b98ac"><span><div id="ed59dfab4b534403a74a1bc40b7b98ac" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ed59dfab4b534403a74a1bc40b7b98ac" title="第二步：用 React 创建一个静态版本"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>第二步：用 React 创建一个静态版本</b></span></span></h4><div class="notion-text notion-block-ee8b971f23474cd78f0e1eef27794ff6">先用已有的数据模型渲染一个不包含交互功能的 UI。最好将渲染 UI 和添加交互这两个过程分开。</div><div class="notion-text notion-block-779eb8fde5cd48eeba105c69ad7170a4">这是因为，编写一个应用的静态版本时，往往要编写大量代码，而不需要考虑太多交互细节；添加交互功能时则要考虑大量细节，而不需要编写太多代码。</div><div class="notion-text notion-block-bb41f5be430548faa1d54110f200a964">在构建应用的静态版本时，我们需要创建一些会重用其他组件的组件，然后通过 <em>props</em> 传入所需的数据。<em>props</em> 是父组件向子组件传递数据的方式。即使你已经熟悉了 <em>state</em> 的概念，也<b>完全不应该使用 state</b> 构建静态版本。state 代表了随时间会产生变化的数据。</div><div class="notion-text notion-block-4ec21f87eeec4241a636d9eae2bd7bef">你可以自上而下或者自下而上构建应用：自上而下意味着首先编写层级较高的组件（比如 <code class="notion-inline-code">FilterableProductTable</code>），自下而上意味着从最基本的组件开始编写（比如 <code class="notion-inline-code">ProductRow</code>）。<b>当你的应用比较简单时，使用自上而下的方式更方便；对于较为大型的项目来说，自下而上地构建，并同时为低层组件编写测试是更加简单的方式。</b></div><div class="notion-text notion-block-dab5ebfd9e8a42189ef84fbd6af71e9d">React <b>单向数据流</b>（也叫<em>单向绑定</em>）的思想使得组件模块化，易于快速开发。</div><div class="notion-text notion-block-0952c48fd91d4a41abb1d2b8eb822a79">在 React 中，<b>有两类“模型”数据：props 和 state</b>。清楚地理解两者的区别是十分重要的</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e01761bf44a1469bac5afb75bb2b74bf" data-id="e01761bf44a1469bac5afb75bb2b74bf"><span><div id="e01761bf44a1469bac5afb75bb2b74bf" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e01761bf44a1469bac5afb75bb2b74bf" title="第三步：确定 UI state 的最小（且完整）表示"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>第三步：确定 UI state 的最小（且完整）表示</b></span></span></h4><div class="notion-text notion-block-4e464be7a54b45ee80e9999c3882706a"><b>只保留应用所需的可变 state 的最小集合，其他数据均由它们计算产生。</b></div><div class="notion-text notion-block-064029d95c364faebd1a0d923e98992f"><b>可以由state计算产生的数据就没必要另外保存一个state！</b></div><div class="notion-text notion-block-637d78abb7ef4070b5403ca6c1f0f971">对于使用props还是state，通过问自己以下三个问题，你可以逐个检查相应数据是否属于 state：</div><ol start="1" class="notion-list notion-list-numbered notion-block-2f61791ccace41d58e0838cc3cf58a38"><li>该数据是否是由父组件通过 props 传递而来的？如果是，那它应该不是 state。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-aba835cf4568410283333287d92b948c"><li>该数据是否随时间的推移而保持不变？如果是，那它应该也不是 state。</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-8f06f22b19e6470b8660e0a758672af0"><li>你能否根据其他 state 或 props 计算出该数据的值？如果是，那它也不是 state。</li></ol><blockquote class="notion-quote notion-block-082e1eb96cc2455d9a765f98dc7b7d9e"><div>非state的数据：</div><ol start="1" class="notion-list notion-list-numbered notion-block-f33e3dcf84ad485ead0ec9855c4428e6"><li>由父组件传来的</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-90a53a49d5174072bddbc3f0e1999ad9"><li>不会随时间推移而改变的</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-f66f9c040c1044d78ef113ba0ae5eb0a"><li>能根据其他stete或props计算而来的</li></ol></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-cae2a4ca108d4242a969239f56592c3e" data-id="cae2a4ca108d4242a969239f56592c3e"><span><div id="cae2a4ca108d4242a969239f56592c3e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#cae2a4ca108d4242a969239f56592c3e" title="第四步：确定 state 放置的位置"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>第四步：确定 state 放置的位置</b></span></span></h4><div class="notion-text notion-block-486cc9983d844f01af209ff9f72980f5">我们需要确定哪个组件能够改变这些 state，或者说<em>拥有</em>这些 state。</div><div class="notion-text notion-block-7073bc26d6754512b0d6dc52b9725e92"><b>注意：React 中的数据流是单向的，并顺着组件层级从上往下传递。</b></div><div class="notion-text notion-block-9994c62097c340aabe8e9a1043ccb574">对于应用中的每一个 state：</div><ul class="notion-list notion-list-disc notion-block-e25435783ae94f3781dc25b8ff9d689e"><li>找到根据这个 state 进行渲染的所有组件。</li></ul><ul class="notion-list notion-list-disc notion-block-8d4b81d3fc5241ef84b1ab9c2f10b73a"><li>找到他们的共同所有者（common owner）组件（在组件层级上高于所有需要该 state 的组件）。</li></ul><ul class="notion-list notion-list-disc notion-block-e607e0a8630c4f22bc01563b6fc89e56"><li>该共同所有者组件或者比它层级更高的组件应该拥有该 state。</li></ul><ul class="notion-list notion-list-disc notion-block-65504661750744c88b5c56c59f83c0c4"><li>如果你找不到一个合适的位置来存放该 state，就可以直接创建一个新的组件来存放该 state，并将这一新组件置于高于共同所有者组件层级的位置</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-5d3608ce99a94338ba6ad69c200ccca2" data-id="5d3608ce99a94338ba6ad69c200ccca2"><span><div id="5d3608ce99a94338ba6ad69c200ccca2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5d3608ce99a94338ba6ad69c200ccca2" title="第五步：添加反向数据流"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>第五步：添加反向数据流</b></span></span></h4><div class="notion-text notion-block-a36bc301de164bb198dde331fc356d90">让<b>数据反向传递：处于较低层级的表单组件更新较高层级组件的state</b></div><div class="notion-text notion-block-79913e843b5e40d09d26b58f0b24949b">实现方式：</div><ol start="1" class="notion-list notion-list-numbered notion-block-feeb72aca4ad44ada93819a2a4cacec2"><li>父组件有一个能够修改state改变的回调函数，并传递给子组件</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-80f56098ebb944a1be8ff2ed310bf4e5"><li>子组件的input修改值，使用<code class="notion-inline-code">onChange</code>事件监听，并执行父组件传入的回调函数。</li></ol></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Websocket]]></title>
            <link>https://www.axin.work/article/98c6e968-f31b-4ae4-a8b2-3b58775c97d1</link>
            <guid>https://www.axin.work/article/98c6e968-f31b-4ae4-a8b2-3b58775c97d1</guid>
            <pubDate>Mon, 29 Jul 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-98c6e968f31b4ae4a8b23b58775c97d1"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-text notion-block-b32fbdabba9b418e9cc75cdebdb6d196">node服务器端代码</div><div class="notion-text notion-block-99f6337d859643fbbfef60d4d28fdcf1">页面相关代码</div><div class="notion-text notion-block-59fb64af763948d7a7a9a02117ca597b">详细代码</div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[TypeScript笔记]]></title>
            <link>https://www.axin.work/article/3b99189e-fd83-4c80-abc4-76932e4e55da</link>
            <guid>https://www.axin.work/article/3b99189e-fd83-4c80-abc4-76932e4e55da</guid>
            <pubDate>Mon, 24 Jun 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-3b99189efd834c80abc476932e4e55da"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-callout notion-gray_background_co notion-block-b59f05187a9b4dccb68de5bbc99417bd"><div class="notion-page-icon-inline notion-page-icon-span"><img class="notion-page-icon" src="https://www.notion.so/icons/airplane_gray.svg?mode=light" alt="开发项目中我们经常会遇到的一些ts报错处理笔记。" loading="lazy" decoding="async"/></div><div class="notion-callout-text">开发项目中我们经常会遇到的一些ts报错处理笔记。</div></div><div class="notion-blank notion-block-d04768a127f7451b8c3fe130d8478a20"> </div><div class="notion-blank notion-block-80adee5e5fae4124a91d000ffb88afc3"> </div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-f9fb7fb69f52426e867d691794c6c76e" data-id="f9fb7fb69f52426e867d691794c6c76e"><span><div id="f9fb7fb69f52426e867d691794c6c76e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f9fb7fb69f52426e867d691794c6c76e" title="📝 TypeScript笔记"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">📝 TypeScript笔记</span></span></h2></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[vue3笔记]]></title>
            <link>https://www.axin.work/article/c621bbd5-f444-4472-8b8d-c967ee9c7406</link>
            <guid>https://www.axin.work/article/c621bbd5-f444-4472-8b8d-c967ee9c7406</guid>
            <pubDate>Sat, 30 Apr 2022 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-c621bbd5f44444728b8dc967ee9c7406"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-1303ef260e1d4dd2b2e69b0cbdc6f4f5" data-id="1303ef260e1d4dd2b2e69b0cbdc6f4f5"><span><div id="1303ef260e1d4dd2b2e69b0cbdc6f4f5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1303ef260e1d4dd2b2e69b0cbdc6f4f5" title="Vue3学习笔记"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Vue3学习笔记</b></span></span></h2><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-e2cb8e4dcf6e4e2db23825c7f5ab8ba0" data-id="e2cb8e4dcf6e4e2db23825c7f5ab8ba0"><span><div id="e2cb8e4dcf6e4e2db23825c7f5ab8ba0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e2cb8e4dcf6e4e2db23825c7f5ab8ba0" title="Vue3简介"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Vue3简介</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7ed46c796139495499ab6409b684c789" data-id="7ed46c796139495499ab6409b684c789"><span><div id="7ed46c796139495499ab6409b684c789" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7ed46c796139495499ab6409b684c789" title="1.性能提升"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1.性能提升</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-d8185b2a3c4f40f7a8cfe99fa6b15bb4"><li>打包大小减少41%；</li></ul><ul class="notion-list notion-list-disc notion-block-ab0179e8ab8c477183ef2c9fe5f873c8"><li>初次渲染快55%，更新渲染快133%；</li></ul><ul class="notion-list notion-list-disc notion-block-8f92d713b2a64f38b6fe75e162554e38"><li>内存减少54%；</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2dfff6fd240b4ebca47f00ee09b16557" data-id="2dfff6fd240b4ebca47f00ee09b16557"><span><div id="2dfff6fd240b4ebca47f00ee09b16557" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2dfff6fd240b4ebca47f00ee09b16557" title="2.源码的升级"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.源码的升级</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-740833945e60485f9047e35ef55bab0e"><li>使用Proxy代替defineProperty实现<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://so.csdn.net/so/search?q=%E5%93%8D%E5%BA%94%E5%BC%8F&amp;spm=1001.2101.3001.7020">响应式</a>。</li></ul><ul class="notion-list notion-list-disc notion-block-a42c5337b02445c7b211bfc943d9d5d8"><li>重写<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://so.csdn.net/so/search?q=%E8%99%9A%E6%8B%9FDom&amp;spm=1001.2101.3001.7020">虚拟Dom</a>的实现和Tree-Shaking</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-6439ded3a2194fc3888c0b7aa52695a2" data-id="6439ded3a2194fc3888c0b7aa52695a2"><span><div id="6439ded3a2194fc3888c0b7aa52695a2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#6439ded3a2194fc3888c0b7aa52695a2" title="3.拥抱TypeScript"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>3.拥抱TypeScript</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-4828c1f6ae2c42e8831c6495996c4f1e"><li>Vue3可以更好的支持TypeScript</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-9d1c4759ec26446491a0f7ba35a41bc6" data-id="9d1c4759ec26446491a0f7ba35a41bc6"><span><div id="9d1c4759ec26446491a0f7ba35a41bc6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#9d1c4759ec26446491a0f7ba35a41bc6" title="4.新的特性"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.新的特性</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-99fd4a8956ed4b649847568b88db77a5"><li><code class="notion-inline-code">Composition API</code>（组合<code class="notion-inline-code">API</code>）：</li><ul class="notion-list notion-list-disc notion-block-99fd4a8956ed4b649847568b88db77a5"><ol start="1" class="notion-list notion-list-numbered notion-block-407a71824336438abca19c39a1582eb1"><li><code class="notion-inline-code">setup</code></li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-6c3ae2f01f2e4717aaa2ae5bde85f5bb"><li><code class="notion-inline-code">ref</code>与<code class="notion-inline-code">reactive</code></li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-372d6d027d404db28c275344717511cc"><li><code class="notion-inline-code">computed</code>与<code class="notion-inline-code">watch</code></li></ol></ul></ul><ul class="notion-list notion-list-disc notion-block-e7d5f9c0d79a41e9b9379517a8752f1c"><li>新的内置组件：</li><ul class="notion-list notion-list-disc notion-block-e7d5f9c0d79a41e9b9379517a8752f1c"><ol start="1" class="notion-list notion-list-numbered notion-block-3737a5cffe4e46a2bb2479273dd9795a"><li><code class="notion-inline-code">Fragment</code></li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-1d3b16e70a13458f9e0e5de8fdcda13f"><li><code class="notion-inline-code">Teleport</code></li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-3a4896cbc8d547999caa0d5c6452bd2a"><li><code class="notion-inline-code">Suspense</code></li></ol></ul></ul><ul class="notion-list notion-list-disc notion-block-25fe6d0d277c4e83ae882fc3c3fa2b29"><li>其他改变：</li><ul class="notion-list notion-list-disc notion-block-25fe6d0d277c4e83ae882fc3c3fa2b29"><ol start="1" class="notion-list notion-list-numbered notion-block-6afa014403a9420c94e5ab96029ac67e"><li>新的生命周期钩子</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-d373415749b84471b1ac7928f607b42a"><li><code class="notion-inline-code">data</code> 选项应始终被声明为一个函数</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-daaadf3a4e3f4b20995cc5f159141d79"><li>移除<code class="notion-inline-code">keyCode</code>支持作为<code class="notion-inline-code">v-on</code> 的修饰符</li></ol></ul></ul><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2924d3235778460ea1320bfb30ab2413" data-id="2924d3235778460ea1320bfb30ab2413"><span><div id="2924d3235778460ea1320bfb30ab2413" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2924d3235778460ea1320bfb30ab2413" title="创建Vue3工程"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>创建Vue3工程</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-11e47bbab5264932b3eee00b590b34f5" data-id="11e47bbab5264932b3eee00b590b34f5"><span><div id="11e47bbab5264932b3eee00b590b34f5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#11e47bbab5264932b3eee00b590b34f5" title="1.基于 vue-cli 创建"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1.基于 vue-cli 创建</b></span></span></h4><div class="notion-text notion-block-8a061d9a656f40d7bdf16d8190e8f52e">运行命令</div><div class="notion-text notion-block-df89320ef7e54ee883e0ff8a651f1f57">接着选择版本 x3</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-95a23342bbb04ef6b60a7e9481632b7e" data-id="95a23342bbb04ef6b60a7e9481632b7e"><span><div id="95a23342bbb04ef6b60a7e9481632b7e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#95a23342bbb04ef6b60a7e9481632b7e" title="2.基于 vite 创建 (推荐)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.基于 vite 创建 (</b><code class="notion-inline-code"><b>推荐</b></code><b>)</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-8a0f70ea31c04a399667c5cf9a2960f9"><li><code class="notion-inline-code">vite</code> 是新一代前端构建工具，官网地址：[<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://vitejs.cn/">https://vitejs.cn</a>]</li><ul class="notion-list notion-list-disc notion-block-8a0f70ea31c04a399667c5cf9a2960f9"><div class="notion-text notion-block-f12405e9e4c44bb898c046025be98945"><code class="notion-inline-code">vite</code>的优势如下：</div><ol start="1" class="notion-list notion-list-numbered notion-block-eb89771211054129960cc8ad3d50d70b"><li>轻量快速的热重载（<code class="notion-inline-code">HMR</code>），能实现极速的服务启动。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-e2470f6971ec4285bfbb10090438cd27"><li>对 <code class="notion-inline-code">TypeScript</code>、<code class="notion-inline-code">JSX</code>、<code class="notion-inline-code">CSS</code> 等支持开箱即用。</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-2a623d1801434939aae5b5b53075d969"><li>真正的按需编译，不再等待整个应用编译完成。</li></ol></ul></ul><ul class="notion-list notion-list-disc notion-block-07467a3b82684f6bb26aa16ce491bfc0"><li>具体操作</li><ul class="notion-list notion-list-disc notion-block-07467a3b82684f6bb26aa16ce491bfc0"></ul></ul><ul class="notion-list notion-list-disc notion-block-cbd7ef21fb934660a1a4646b9695f896"><li>编写一个App组件</li><ul class="notion-list notion-list-disc notion-block-cbd7ef21fb934660a1a4646b9695f896"><div class="notion-text notion-block-398adf09d8c34596a129b5c3ef8b91ee">总结：</div><ol start="1" class="notion-list notion-list-numbered notion-block-e4153c18660840a49b8602a71bd4c2d4"><li><code class="notion-inline-code">Vite</code> 项目中，<code class="notion-inline-code">index.html</code> 是项目的入口文件，在项目最外层。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-a5a7e935db2545f1874b5e03bf14f56e"><li>加载<code class="notion-inline-code">index.html</code>后，<code class="notion-inline-code">Vite</code> 解析 <code class="notion-inline-code">&lt;script type=&quot;module&quot; src=&quot;xxx&quot;&gt;</code> 指向的<code class="notion-inline-code">JavaScript</code>。</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-ab856eb0189a41a28e89fb76eee25a3c"><li><code class="notion-inline-code">Vue3</code><b>中是通过 </b><code class="notion-inline-code">createApp</code> 函数创建一个应用实例。</li></ol><ol start="4" class="notion-list notion-list-numbered notion-block-f322b41d940642168f9e45d19442f487"><li><code class="notion-inline-code">Vue3</code>向下兼容<code class="notion-inline-code">Vue2</code>语法，且<code class="notion-inline-code">Vue3</code>中的模板中可以没有根标签</li></ol></ul></ul><ul class="notion-list notion-list-disc notion-block-bfc91edbd8004c259a3c07698761e1ef"><li>一个简单的效果</li><ul class="notion-list notion-list-disc notion-block-bfc91edbd8004c259a3c07698761e1ef"></ul></ul><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-380efc60a0574fbbb230cac4d2bbf9ba" data-id="380efc60a0574fbbb230cac4d2bbf9ba"><span><div id="380efc60a0574fbbb230cac4d2bbf9ba" class="notion-header-anchor"></div><a class="notion-hash-link" href="#380efc60a0574fbbb230cac4d2bbf9ba" title="Vue3核心语法"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Vue3核心语法</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1f77073fedb041dc91dfa4c03a77dffc" data-id="1f77073fedb041dc91dfa4c03a77dffc"><span><div id="1f77073fedb041dc91dfa4c03a77dffc" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1f77073fedb041dc91dfa4c03a77dffc" title="1.OptionsAPI 与 CompositionAPI"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1.OptionsAPI 与 CompositionAPI</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-cc82ad275e9b46069d2e0e2faca1222c"><li><code class="notion-inline-code">Vue2</code>的<code class="notion-inline-code">API</code>设计是<code class="notion-inline-code">Options</code>（配置）风格的。</li></ul><ul class="notion-list notion-list-disc notion-block-cc97d48606d8482ebeae0292ba4dbc3b"><li><code class="notion-inline-code">Vue3</code>的<code class="notion-inline-code">API</code>设计是<code class="notion-inline-code">Composition</code>（组合）风格的。</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-470550ac8b8f4902ae0db5b38974a909" data-id="470550ac8b8f4902ae0db5b38974a909"><span><div id="470550ac8b8f4902ae0db5b38974a909" class="notion-header-anchor"></div><a class="notion-hash-link" href="#470550ac8b8f4902ae0db5b38974a909" title="Options API 的弊端"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Options API 的弊端</b></span></span></h4><div class="notion-text notion-block-481798b5ba504ad3b71588da76615818"><code class="notion-inline-code">Options</code>类型的 <code class="notion-inline-code">API</code>，数据、方法、计算属性等，是分散在：<code class="notion-inline-code">data</code>、<code class="notion-inline-code">methods</code>、<code class="notion-inline-code">computed</code>中的，若想新增或者修改一个需求，就需要分别修改：<code class="notion-inline-code">data</code>、<code class="notion-inline-code">methods</code>、<code class="notion-inline-code">computed</code>，不便于维护和复用。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-9e706c00d20f47a4bb58c9e8e95fe43f" data-id="9e706c00d20f47a4bb58c9e8e95fe43f"><span><div id="9e706c00d20f47a4bb58c9e8e95fe43f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#9e706c00d20f47a4bb58c9e8e95fe43f" title="Composition API 的优势"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Composition API 的优势</b></span></span></h4><div class="notion-text notion-block-f4a01e190ba642c3af84c43cc7e0e9d1">可以用函数的方式，更加优雅的组织代码，让相关功能的代码更加有序的组织在一起。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-47cef7fe9f58410f83101da1c573b6c4" data-id="47cef7fe9f58410f83101da1c573b6c4"><span><div id="47cef7fe9f58410f83101da1c573b6c4" class="notion-header-anchor"></div><a class="notion-hash-link" href="#47cef7fe9f58410f83101da1c573b6c4" title="2.拉开序幕的setup"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.拉开序幕的</b><code class="notion-inline-code"><b>setup</b></code></span></span></h4><div class="notion-text notion-block-223f9a2d2e8a4057adf005dc73c3de49"><code class="notion-inline-code">setup</code>是<code class="notion-inline-code">Vue3</code>中一个新的配置项，值是一个函数，它是 <code class="notion-inline-code">Composition API</code> <b>“表演的舞台</b><em><b>”</b></em>，组件中所用到的：数据、方法、计算属性、监视......等等，均配置在<code class="notion-inline-code">setup</code>中。</div><ul class="notion-list notion-list-disc notion-block-dc4382a85b344802b0bacd7c8d4e13d8"><li>传统选项式</li><ul class="notion-list notion-list-disc notion-block-dc4382a85b344802b0bacd7c8d4e13d8"></ul></ul><ul class="notion-list notion-list-disc notion-block-baa5209e7ff84abebf19f54fde61d81b"><li>vue3组合式</li><ul class="notion-list notion-list-disc notion-block-baa5209e7ff84abebf19f54fde61d81b"><div class="notion-text notion-block-908b418582274bdd87de21e74fd3076b">特点如下：</div><li><code class="notion-inline-code">setup</code>函数返回的对象中的内容，可直接在模板中使用。
- <code class="notion-inline-code">setup</code>中访问<code class="notion-inline-code">this</code>是<code class="notion-inline-code">undefined</code>。
- <code class="notion-inline-code">setup</code>函数会在<code class="notion-inline-code">beforeCreate</code>之前调用，它是“领先”所有钩子执行的。</li><div class="notion-text notion-block-0aeb2a3ab7604b099f2e3abb965bfa16">（Vue3中弱化了this）</div></ul></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-3003c532a4c74ca2b626399151f4d2c1" data-id="3003c532a4c74ca2b626399151f4d2c1"><span><div id="3003c532a4c74ca2b626399151f4d2c1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3003c532a4c74ca2b626399151f4d2c1" title="2.1 setup的返回值"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.1 setup的返回值</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-a0dbf349d222408bbab458bad7021b0b"><li>若返回一个<b>对象</b>：则对象中的：属性、方法等，在模板中均可以直接使用（重点关注）。</li></ul><ul class="notion-list notion-list-disc notion-block-b76e6144b4b14a01981eec373f6cd8ea"><li>若返回一个<b>函数</b>：则可以自定义渲染内容，代码如下：</li><ul class="notion-list notion-list-disc notion-block-b76e6144b4b14a01981eec373f6cd8ea"></ul></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-4c99995c5061469d91cb13862511cec8" data-id="4c99995c5061469d91cb13862511cec8"><span><div id="4c99995c5061469d91cb13862511cec8" class="notion-header-anchor"></div><a class="notion-hash-link" href="#4c99995c5061469d91cb13862511cec8" title="2.2 setup与Options API的关系"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.2 setup与Options API的关系</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-9eb637fccc1e4569ae7e201c90535668"><li><code class="notion-inline-code">Vue2</code> 的配置（<code class="notion-inline-code">data</code>、<code class="notion-inline-code">methods</code>）中可以访问到<code class="notion-inline-code">setup</code>中的属性、方法。（因为setup处于beforecreate之前）</li></ul><ul class="notion-list notion-list-disc notion-block-2141292c12344f409769628638b18091"><li>但在<code class="notion-inline-code">setup</code>中不能访问到<code class="notion-inline-code">Vue2</code>的配置（<code class="notion-inline-code">data</code>、<code class="notion-inline-code">methods</code>）。</li></ul><ul class="notion-list notion-list-disc notion-block-c560c5794c8742b595b1feebad914a6e"><li>如果与<code class="notion-inline-code">Vue2</code>冲突，则<code class="notion-inline-code">setup</code>优先。</li></ul><div class="notion-text notion-block-4a401fd021c74cbd9f9d3bb79649c95b"><code class="notion-inline-code">（setup没有this。里面不能写this）</code></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2798a55e26ce44589f6c2ca780d848fd" data-id="2798a55e26ce44589f6c2ca780d848fd"><span><div id="2798a55e26ce44589f6c2ca780d848fd" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2798a55e26ce44589f6c2ca780d848fd" title="3.setup语法糖"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>3.setup语法糖</b></span></span></h4><div class="notion-text notion-block-f3a9417c9b304ea6bb056bd0e090f2bf">代码：</div><div class="notion-text notion-block-0316d2076603429393f5071f25765cb4">扩展：上述代码，还需要编写一个不写<code class="notion-inline-code">setup</code>的<code class="notion-inline-code">script</code>标签，去指定组件名字，比较麻烦，我们可以借助<code class="notion-inline-code">vite</code>中的插件简化</div><ol start="1" class="notion-list notion-list-numbered notion-block-c16500c539dc4d05b777c65cc241af08"><li>第一步：在终端中<code class="notion-inline-code">npm i vite-plugin-vue-setup-extend -D</code></li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-36dd05ef75c24b9abb1e934065e8f68d"><li>第二步：打开<code class="notion-inline-code">vite.config.ts</code>文件，改为：</li><ol class="notion-list notion-list-numbered notion-block-36dd05ef75c24b9abb1e934065e8f68d"></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-1ba316d201654acb8878d5fc82852d2b"><li>第三步：<code class="notion-inline-code">&lt;script setup lang=&quot;ts&quot; name=&quot;Person&quot;&gt;</code></li></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-93f086243d23450b8d33311e65a150af" data-id="93f086243d23450b8d33311e65a150af"><span><div id="93f086243d23450b8d33311e65a150af" class="notion-header-anchor"></div><a class="notion-hash-link" href="#93f086243d23450b8d33311e65a150af" title="4.【ref 创建：基本类型的响应式数据】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.【ref 创建：基本类型的响应式数据】</b></span></span></h4><div class="notion-text notion-block-082db2556cd0460f90fa433e2d9c5762">（该ref与vue2中的ref不同。该ref是可以使数据变为响应式的，哪个是响应式，就给哪个加）</div><ul class="notion-list notion-list-disc notion-block-4bd2878c460d4bb982d0db7f8bc7a2d9"><li>作用：定义响应式变量。</li></ul><ul class="notion-list notion-list-disc notion-block-9bf40bbf611b4f9e8270b05b70152164"><li>语法：<code class="notion-inline-code">let xxx = ref(初始值)</code>。</li></ul><ul class="notion-list notion-list-disc notion-block-fa60df8254494a59b5edff29f7ae4ec4"><li>返回值：一个<code class="notion-inline-code">RefImpl</code>的实例对象，简称<code class="notion-inline-code">ref对象</code>或<code class="notion-inline-code">ref</code>，<code class="notion-inline-code">ref</code>对象的<code class="notion-inline-code">value</code>属性是响应式的。</li></ul><ul class="notion-list notion-list-disc notion-block-4b73ca88cbb4428b8e97c2042984790b"><li>注意点：</li><ul class="notion-list notion-list-disc notion-block-4b73ca88cbb4428b8e97c2042984790b"><li><code class="notion-inline-code">JS</code>中操作数据需要：<code class="notion-inline-code">xxx.value</code>，但模板中不需要<code class="notion-inline-code">.value</code>，直接使用即可。</li><li>对于<code class="notion-inline-code">let name = ref(&#x27;张三&#x27;)</code>来说，<code class="notion-inline-code">name</code>不是响应式的，<code class="notion-inline-code">name.value</code>是响应式的。（JS中操作ref对象时候需要.value）</li></ul></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-f1f17b380b394aca91924918e6ded16a" data-id="f1f17b380b394aca91924918e6ded16a"><span><div id="f1f17b380b394aca91924918e6ded16a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f1f17b380b394aca91924918e6ded16a" title="5.【reactive 创建：对象类型的响应式数据】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>5.【reactive 创建：对象类型的响应式数据】</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-b1759931ed43452b90f8976cd876bc86"><li>作用：定义一个响应式对象（基本类型不要用它，要用<code class="notion-inline-code">ref</code>，否则报错）</li></ul><ul class="notion-list notion-list-disc notion-block-37f0880cf83744a5812f57336cacf426"><li>语法：<code class="notion-inline-code">let 响应式对象= reactive(源对象)</code>。</li></ul><ul class="notion-list notion-list-disc notion-block-030b905de8864ca3b7658e8100942d8a"><li>返回值：一个<code class="notion-inline-code">Proxy</code>的实例对象，简称：响应式对象。</li></ul><ul class="notion-list notion-list-disc notion-block-24a6a970795e4e3ab6caad2d333a359e"><li>注意点：<code class="notion-inline-code">reactive</code>定义的响应式数据是“深层次”的。</li></ul><div class="notion-text notion-block-cecb57a954d54d26b4bc23f1e62504e2">（Shift + Alt + 上/下箭头 选中代码往上/下面复制）</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-edac2f7af6f443e58c149515c77c9b55" data-id="edac2f7af6f443e58c149515c77c9b55"><span><div id="edac2f7af6f443e58c149515c77c9b55" class="notion-header-anchor"></div><a class="notion-hash-link" href="#edac2f7af6f443e58c149515c77c9b55" title="6.【ref 创建：对象类型的响应式数据】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>6.【ref 创建：对象类型的响应式数据】</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-fed1969f576e4007a386d883af2ca7b5"><li>其实<code class="notion-inline-code">ref</code>接收的数据可以是：基本类型、对象类型。</li></ul><ul class="notion-list notion-list-disc notion-block-2b10e66352de44179b60a79dc889b278"><li>若<code class="notion-inline-code">ref</code>接收的是对象类型，内部其实也是调用了<code class="notion-inline-code">reactive</code>函数。</li></ul><div class="notion-text notion-block-9a169065437c4a898dc3def1d85a82e9">（reactive只能定义对象类型的响应式数据）</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ad58dec82ee5413ab4e0a7a25aac68ca" data-id="ad58dec82ee5413ab4e0a7a25aac68ca"><span><div id="ad58dec82ee5413ab4e0a7a25aac68ca" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ad58dec82ee5413ab4e0a7a25aac68ca" title="7.【ref 对比 reactive】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>7.【ref 对比 reactive】</b></span></span></h4><div class="notion-text notion-block-58afc294a939476c9b53dd94b35f86f4">宏观角度看：</div><blockquote class="notion-quote notion-block-22bbdc0f48b54ae4870d774e48f6e0b9"><div>ref用来定义：基本类型数据、对象类型数据；reactive用来定义：对象类型数据。</div></blockquote><div class="notion-text notion-block-315a48abdd4c4ecbbfbf844c0d4023c7">区别：</div><blockquote class="notion-quote notion-block-69b73110f5004969b53eb00b05492255"><div>ref创建的变量必须使用.value（可以使用volar插件自动添加.value）。reactive重新分配一个新对象，会失去响应式（可以使用Object.assign去整体替换）。</div></blockquote><div class="notion-text notion-block-2b82329cab9c4ffca9e6bce004643403">使用原则：</div><blockquote class="notion-quote notion-block-2aa6af7eb057408ca68e1a0616544b13"><div>若需要一个基本类型的响应式数据，必须使用ref。若需要一个响应式对象，层级不深，ref、reactive都可以。若需要一个响应式对象，且层级较深，推荐使用reactive。做表单相关的数据，推荐使用reactive。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-b3bdba30ec624ea79dcc84346606f957" data-id="b3bdba30ec624ea79dcc84346606f957"><span><div id="b3bdba30ec624ea79dcc84346606f957" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b3bdba30ec624ea79dcc84346606f957" title="8.【toRefs 与 toRef】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>8.【toRefs 与 toRef】</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-edc49dd556fb472eb40521df764122db"><li>作用：将一个响应式对象中的每一个属性，转换为<code class="notion-inline-code">ref</code>对象。</li></ul><ul class="notion-list notion-list-disc notion-block-b30efc048069480194ea642e6037b4c7"><li>备注：<code class="notion-inline-code">toRefs</code>与<code class="notion-inline-code">toRef</code>功能一致，但<code class="notion-inline-code">toRefs</code>可以批量转换。</li></ul><ul class="notion-list notion-list-disc notion-block-2b380eef03f843c1a2796e3373418535"><li>toRefs是把整个reactive所定义的对象的每一组key-value都拿出来形成一个新的对象并且还具备响应式的能力</li></ul><ul class="notion-list notion-list-disc notion-block-8c95cb654f234cfeae0333287bc3af5e"><li>语法如下：</li><ul class="notion-list notion-list-disc notion-block-8c95cb654f234cfeae0333287bc3af5e"></ul></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7ecd156413634da6b6774fcbcde35397" data-id="7ecd156413634da6b6774fcbcde35397"><span><div id="7ecd156413634da6b6774fcbcde35397" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7ecd156413634da6b6774fcbcde35397" title="9.【computed计算属性】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>9.【computed计算属性】</b></span></span></h4><div class="notion-text notion-block-7a00b116b95f4b4fb2a5b8dc2b7c1e74">作用：根据已有数据计算出新数据（和<code class="notion-inline-code">Vue2</code>中的<code class="notion-inline-code">computed</code>作用一致）。</div><div class="notion-text notion-block-78829c739bac4410afa7c3584931a086">底层借助了object.defineproperty方法提供的getter和setter</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-50778793d11b42b29fc2b2454142c14a" data-id="50778793d11b42b29fc2b2454142c14a"><span><div id="50778793d11b42b29fc2b2454142c14a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#50778793d11b42b29fc2b2454142c14a" title="10.【watch监听】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>10.【watch监听】</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-839352897813452597eaa75762995e0a"><li>作用：监视数据的变化（和<code class="notion-inline-code">Vue2</code>中的<code class="notion-inline-code">watch</code>作用一致）</li></ul><ul class="notion-list notion-list-disc notion-block-859b057ff8af4d3fb2015549e2c8bf41"><li>特点：<code class="notion-inline-code">Vue3</code>中的<code class="notion-inline-code">watch</code>只能监视以下四种数据：</li></ul><blockquote class="notion-quote notion-block-882d98ec2a004ed6b4e7d776061835bf"><div>ref定义的数据。reactive定义的数据。函数返回一个值（getter函数）。一个包含上述内容的数组。</div></blockquote><div class="notion-text notion-block-e9974e2293d2436d899894a2a889ab64">(官方文档</div><div class="notion-text notion-block-9f8d849df98c48738d583e5806d6141e">watch() 默认是懒侦听的，即仅在侦听源发生变化时才执行回调函数。</div><div class="notion-text notion-block-95b6dfe6f0b241a0bc94617c56154082">第一个参数是侦听器的源。这个来源可以是以下几种：</div><div class="notion-text notion-block-6656d9d73c654a1db40b94de9aefa819">一个函数，返回一个值
一个 ref
一个响应式对象
...或是由以上类型的值组成的数组
)</div><div class="notion-text notion-block-634613f1b220413fa49d2a0e632f9792">我们在<code class="notion-inline-code">Vue3</code>中使用<code class="notion-inline-code">watch</code>的时候，通常会遇到以下几种情况：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-def0e44d9145439585d83e5ed307efad" data-id="def0e44d9145439585d83e5ed307efad"><span><div id="def0e44d9145439585d83e5ed307efad" class="notion-header-anchor"></div><a class="notion-hash-link" href="#def0e44d9145439585d83e5ed307efad" title="情况一"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>情况一</b></span></span></h4><div class="notion-text notion-block-13c866b2c4b44f05b6759d5952b45dab">监视<code class="notion-inline-code">ref</code>定义的【基本类型】数据：直接写数据名即可，监视的是其<code class="notion-inline-code">value</code>值的改变。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7328227863d04628bb5bb9c193200fb6" data-id="7328227863d04628bb5bb9c193200fb6"><span><div id="7328227863d04628bb5bb9c193200fb6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7328227863d04628bb5bb9c193200fb6" title="情况二"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>情况二</b></span></span></h4><div class="notion-text notion-block-a32a96456e614e36b45eb3a00f6b47e4">监视<code class="notion-inline-code">ref</code>定义的【对象类型】数据：直接写数据名，监视的是对象的【地址值】，若想监视对象内部的数据，要手动开启深度监视。</div><div class="notion-text notion-block-633b077fc26b4b04890db32265a99c13">注意：</div><blockquote class="notion-quote notion-block-29ac3820173c4ce0aaf7e6ae787ce646"><div>若修改的是ref定义的对象中的属性，newValue 和 oldValue 都是新值，因为它们是同一个对象。
若修改整个ref定义的对象，newValue 是新值， oldValue 是旧值，因为不是同一个对象了。</div></blockquote><blockquote class="notion-quote notion-block-5dac461d9b5144849c24fe6dbac0100d"><div>监视，情况一：监视【ref】定义的【对象类型】数据，监视的是对象的地址值，只有整个对象被改变的时候才会被监视到。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-81a55ba6d10b4c1786f85983bc7360a0" data-id="81a55ba6d10b4c1786f85983bc7360a0"><span><div id="81a55ba6d10b4c1786f85983bc7360a0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#81a55ba6d10b4c1786f85983bc7360a0" title="情况三"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>情况三</b></span></span></h4><div class="notion-text notion-block-6ff7db24b4954ef99c7e7d4101193c95">监视<code class="notion-inline-code">reactive</code>定义的【对象类型】数据，且默认开启了深度监视。</div><div class="notion-text notion-block-c387d2e30a4c4dc19fc1f41e261ba6c9">（reactive隐式创建深层监听，并且该深度监视没法关闭）</div><div class="notion-text notion-block-87705bd3da984e3baf138fb497f74fdf">对比ref与reactive修改整个对象的方法</div><div class="notion-text notion-block-1b74aa81e8284cb08c994b21afc08fb0">代码：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-54a2edb5eb414b5fa1c385b1a9856c66" data-id="54a2edb5eb414b5fa1c385b1a9856c66"><span><div id="54a2edb5eb414b5fa1c385b1a9856c66" class="notion-header-anchor"></div><a class="notion-hash-link" href="#54a2edb5eb414b5fa1c385b1a9856c66" title="情况四"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>情况四</b></span></span></h4><div class="notion-text notion-block-2afa510e1c12497ab5979695d3286169">监视<code class="notion-inline-code">ref</code>或<code class="notion-inline-code">reactive</code>定义的【对象类型】数据中的某个属性，（遇到该情况，反手就用函数）注意点如下：</div><ol start="1" class="notion-list notion-list-numbered notion-block-cf78cbaf6a55464db8a72da213362823"><li>若该属性值不是【对象类型】，需要写成函数形式。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-7eeee7295c2a4930ba0171740b0eeffe"><li>若该属性值是依然是【对象类型】，可直接编，也可写成函数，建议写成函数。</li></ol><div class="notion-text notion-block-992091b6a72d44d5b6fffe269d7cc7b3">结论：监视的要是对象里的属性，那么最好写函数式，注意点：若是对象监视的是地址值，需要关注对象内部，需要手动开启深度监视。</div><div class="notion-text notion-block-d6f86526f8994289966f1b2e2eccb9ce">代码：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-f8242a45e666458e8c046f7164763c64" data-id="f8242a45e666458e8c046f7164763c64"><span><div id="f8242a45e666458e8c046f7164763c64" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f8242a45e666458e8c046f7164763c64" title="情况五"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>情况五</b></span></span></h4><div class="notion-text notion-block-8eee4ab88aaa4653bf229a763794ebdd">监视上述的多个数据</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7a1faeab7f264e0ca889292af5b92280" data-id="7a1faeab7f264e0ca889292af5b92280"><span><div id="7a1faeab7f264e0ca889292af5b92280" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7a1faeab7f264e0ca889292af5b92280" title="11.【watchEffect】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>11.【watchEffect】</b></span></span></h4><div class="notion-text notion-block-4e16b7b778e640668edb93fbefd71f3c">官网：立即运行一个函数，同时响应式地追踪其依赖，并在依赖更改时重新执行该函数。</div><div class="notion-text notion-block-f6ac3875216442469e558a348c18916e"><code class="notion-inline-code">watch</code>对比<code class="notion-inline-code">watchEffect</code></div><blockquote class="notion-quote notion-block-8001bb48eb7040bc8af05dbc51283234"><div>都能监听响应式数据的变化，不同的是监听数据变化的方式不同watch：要明确指出监视的数据，watch是惰性的，你让他监视谁才监视谁watchEffect：不用明确指出监视的数据（函数中用到哪些属性，那就监视哪些属性）。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-eda422557c9a40f3bd8c4fdcce19ef81" data-id="eda422557c9a40f3bd8c4fdcce19ef81"><span><div id="eda422557c9a40f3bd8c4fdcce19ef81" class="notion-header-anchor"></div><a class="notion-hash-link" href="#eda422557c9a40f3bd8c4fdcce19ef81" title="12.【标签的 ref 属性】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.【标签的 ref 属性】</b></span></span></h4><div class="notion-text notion-block-589fdeffe66947fa9bc73b5ef89bef7d">作用：用于注册模板引用。</div><blockquote class="notion-quote notion-block-bca6af2d6f194027961d86749f0436b4"><div>用在普通DOM标签上，获取的是DOM节点。用在组件标签上，获取的是组件实例对象。</div></blockquote><div class="notion-text notion-block-5cea5ac2abe0428e945a3cece95ab65d">用在普通<code class="notion-inline-code">DOM</code>标签上：</div><div class="notion-text notion-block-5f80d92577f0452699e47afabd25262a">用在组件标签上：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-93417940d95545b69de05c8c368d8629" data-id="93417940d95545b69de05c8c368d8629"><span><div id="93417940d95545b69de05c8c368d8629" class="notion-header-anchor"></div><a class="notion-hash-link" href="#93417940d95545b69de05c8c368d8629" title="13.【props】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>13.【props】</b></span></span></h4><div class="notion-text notion-block-1a9c48b403e241f2a5502adac88b751b"><b>路径别名报错注意：</b></div><div class="notion-text notion-block-4a855a3a1523407f85e3923d353cfb03">如果在引入&quot;@&quot;符号以下报错的时候，出现</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-e901f908d51f4286929c5c4ce8be45a7"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F2c930dfe-da21-46e5-a4f5-114f9750f2d0%2F74712f20-66d3-4e2f-b11a-9c59a06e03c7%2F%25E5%25BC%2595%25E5%2585%25A5%25E8%25B7%25AF%25E5%25BE%2584%25E6%258A%25A5%25E9%2594%2599.png?table=block&amp;id=e901f908-d51f-4286-929c-5c4ce8be45a7&amp;t=e901f908-d51f-4286-929c-5c4ce8be45a7&amp;width=708&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-e078b463b2694d8894f5a4b7008ef4a8">这个错误通常是由于找不到所需的模块或类型声明文件引起的。在 Vue 3 项目中，使用@引入根目录是一个常见的路径别名设置。</div><div class="notion-text notion-block-e124fa674bab4a3999faaf3dafa12666">要解决这个问题，你需要在你的项目中进行一些配置：</div><ol start="1" class="notion-list notion-list-numbered notion-block-23cb7bb3f228496197164b8fe9c3c893"><li>在项目的根目录下找到 tsconfig.json 文件（如果没有，请创建一个）。这是 TypeScript 的配置文件。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-37bdcd03464844ae89237cae0edcb0e9"><li>在 tsconfig.json 文件中，添加一个 &quot;baseUrl&quot; 属性，指定你的根目录的路径</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-ba648f4ed1434fcda545a4c7be818b73"><li>如果你使用了路径别名，比如 &quot;@&quot;，你还需要添加一个 &quot;paths&quot; 属性来映射路径别名到实际的文件路径。</li></ol><ol start="4" class="notion-list notion-list-numbered notion-block-f130bf9a9d284f67b27861549711d3eb"><li>tsconfig.json 文件代码如下：</li><ol class="notion-list notion-list-numbered notion-block-f130bf9a9d284f67b27861549711d3eb"></ol></ol><div class="notion-text notion-block-b189c627ddd347fb83e9c5a6930acce7"><b>index.ts代码：</b></div><div class="notion-text notion-block-37eb6b1e0ccd40d089e72db0f6c4761c"><b>App.vue代码</b>：</div><div class="notion-text notion-block-784b15ce7955433a8a104aeee83912aa"><b>Person.vue代码</b>：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-f1925c21c7bd472684aaa5c9b3752783" data-id="f1925c21c7bd472684aaa5c9b3752783"><span><div id="f1925c21c7bd472684aaa5c9b3752783" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f1925c21c7bd472684aaa5c9b3752783" title="14.【生命周期】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>14.【生命周期】</b></span></span></h4><div class="notion-text notion-block-84367a705fe141c99c93c1ea90d3172d"><em>概念</em>：<code class="notion-inline-code">Vue</code>组件实例在创建时要经历一系列的初始化步骤，在此过程中<code class="notion-inline-code">Vue</code>会在合适的时机，调用特定的函数，从而让开发者有机会在特定阶段运行自己的代码，这些特定的函数统称为：生命周期钩子</div><ul class="notion-list notion-list-disc notion-block-d3cafe6375cc4be0bc947771fef3fa52"><li>规律：</li><ul class="notion-list notion-list-disc notion-block-d3cafe6375cc4be0bc947771fef3fa52"><blockquote class="notion-quote notion-block-6fa1231dc63241649a6bad04a8caab38"><div>生命周期整体分为四个阶段，分别是：创建、挂载、更新、销毁，每个阶段都有两个钩子，一前一后。</div></blockquote></ul></ul><ul class="notion-list notion-list-disc notion-block-d63cae8144214076b30f7e5f66c04c5b"><li><code class="notion-inline-code">Vue2</code>的生命周期</li><ul class="notion-list notion-list-disc notion-block-d63cae8144214076b30f7e5f66c04c5b"><blockquote class="notion-quote notion-block-c91f97bf87e842c3aa5189c348674d83"><div>创建阶段：beforeCreate、created
挂载阶段：beforeMount、mounted
更新阶段：beforeUpdate、updated
销毁阶段：beforeDestroy、destroyed</div></blockquote></ul></ul><ul class="notion-list notion-list-disc notion-block-549ca6b7e1ec4fdb9cc2e781f6206f77"><li><code class="notion-inline-code">Vue3</code>的生命周期</li><ul class="notion-list notion-list-disc notion-block-549ca6b7e1ec4fdb9cc2e781f6206f77"><blockquote class="notion-quote notion-block-908057c6934b4c488a5d8d9c9998da59"><div>创建阶段：setup
挂载阶段：onBeforeMount、onMounted
更新阶段：onBeforeUpdate、onUpdated
卸载阶段：onBeforeUnmount、onUnmounted</div></blockquote></ul></ul><ul class="notion-list notion-list-disc notion-block-b383cb2d97c94ec2bdab021dc1d0a8bd"><li>常用的钩子：<code class="notion-inline-code">onMounted</code>(挂载完毕)、<code class="notion-inline-code">onUpdated</code>(更新完毕)、<code class="notion-inline-code">onBeforeUnmount</code>(卸载之前)</li></ul><div class="notion-text notion-block-8b3eab1aabc84ec68508b19ee37f0b88">（注意：在组件中，需要先把子组件挂载完毕，最后再挂载父组件App，因为父组件的最上面就是引用的一些子组件，必须先把所有的子组件挂载完毕以后。才会挂载父组件。有点像深度优先遍历）</div><div class="notion-text notion-block-4a4c29224b654868b2350ee63768998d">代码：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-cf67f678f9694d2980a354b45dca4663" data-id="cf67f678f9694d2980a354b45dca4663"><span><div id="cf67f678f9694d2980a354b45dca4663" class="notion-header-anchor"></div><a class="notion-hash-link" href="#cf67f678f9694d2980a354b45dca4663" title="15.【自定义hook】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>15.【自定义hook】</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-7606a2c52b634823a7d1313a384dae9f"><li>什么是<code class="notion-inline-code">hook</code>？—— 本质是一个函数，把<code class="notion-inline-code">setup</code>函数中使用的<code class="notion-inline-code">Composition API</code>进行了封装，类似于<code class="notion-inline-code">vue2.x</code>中的<code class="notion-inline-code">mixin</code>。</li></ul><ul class="notion-list notion-list-disc notion-block-a04c28f803254d1a95d2ae2cea3371e5"><li>自定义<code class="notion-inline-code">hook</code>的优势：复用代码, 让<code class="notion-inline-code">setup</code>中的逻辑更清楚易懂。</li></ul><div class="notion-text notion-block-69720d69cbc14af085bd320cf9fd56ad"><code class="notion-inline-code">useSum.ts</code>中内容如下：</div><div class="notion-text notion-block-c6ef834e7dba45f9bbd3a1d9d9bd2303"><code class="notion-inline-code">useDog.ts</code>中内容如下：</div><div class="notion-text notion-block-d51e13a4c0954bcba88721c385818988">组件中具体使用：</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-3352e149f46c4019814bec31d919b701" data-id="3352e149f46c4019814bec31d919b701"><span><div id="3352e149f46c4019814bec31d919b701" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3352e149f46c4019814bec31d919b701" title="路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-0363667006384384836f81c240f9f7d6" data-id="0363667006384384836f81c240f9f7d6"><span><div id="0363667006384384836f81c240f9f7d6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0363667006384384836f81c240f9f7d6" title="1.【对路由的理解】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1.【对路由的理解】</b></span></span></h4><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-dd65f44e2194481a800ff8e35a3776fa"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F2c930dfe-da21-46e5-a4f5-114f9750f2d0%2Fcf3acb28-3e9e-4e66-840f-0e356398a7c0%2F%25E8%25B7%25AF%25E7%2594%25B1%25E7%2590%2586%25E8%25A7%25A3.png?table=block&amp;id=dd65f44e-2194-481a-800f-f8e35a3776fa&amp;t=dd65f44e-2194-481a-800f-f8e35a3776fa&amp;width=2216&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-39fb90981c1444799be6dfd1f573ed7a" data-id="39fb90981c1444799be6dfd1f573ed7a"><span><div id="39fb90981c1444799be6dfd1f573ed7a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#39fb90981c1444799be6dfd1f573ed7a" title="2.【基本切换效果】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.【基本切换效果】</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-c3314ac81f55410aa68190d646e52ecc"><li><code class="notion-inline-code">Vue3</code>中要使用<code class="notion-inline-code">vue-router</code>的最新版本，目前是<code class="notion-inline-code">4</code>版本。</li></ul><div class="notion-text notion-block-88a9dac5500f4470bffd9377b02fe5c3">npm i vue-router</div><ul class="notion-list notion-list-disc notion-block-a78c5c3c664c43b2933ea93925a3fd6f"><li>路由配置文件代码如下：</li></ul><div class="notion-text notion-block-790daf41f7b649c6bf62e04129b7dd69"><b>Index.ts代码</b>：</div><div class="notion-text notion-block-7bbc9d8c1e1e474183961c2bb86883e4"><b>main.ts代码</b>:</div><div class="notion-text notion-block-aa700e845d2f4c7ab5cdefd16f8390a6"><code class="notion-inline-code"><b>App.vue</b></code><b>代码如下</b></div><div class="notion-text notion-block-e34e47f00a524bf4a9c82816da3f88ae">注意：需要在App组件中引入RouterLink，RouterLink是标签，把a标签改成RouterLink，里面的href也改成to。激活高亮是active-class</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-a6f2585c215749d0beab5099ad5765a6" data-id="a6f2585c215749d0beab5099ad5765a6"><span><div id="a6f2585c215749d0beab5099ad5765a6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a6f2585c215749d0beab5099ad5765a6" title="3.【两个注意点】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>3.【两个注意点】</b></span></span></h4><blockquote class="notion-quote notion-block-a3af836cb1e04c4cb55045720c161855"><div>路由组件通常存放在pages 或 views文件夹，一般组件通常存放在components文件夹。通过点击导航，视觉效果上“消失” 了的路由组件，默认是被卸载掉的，需要的时候再去挂载。</div></blockquote><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-e86009c91eb34783964cc963b1614e8b"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F2c930dfe-da21-46e5-a4f5-114f9750f2d0%2F35ae34f1-f510-4d69-b5de-50473fc9b02c%2F%25E4%25B8%25A4%25E4%25B8%25AA%25E6%25B3%25A8%25E6%2584%258F%25E7%2582%25B9.png?table=block&amp;id=e86009c9-1eb3-4783-964c-c963b1614e8b&amp;t=e86009c9-1eb3-4783-964c-c963b1614e8b&amp;width=2384&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-dcfac1eb196f452b8076e62a5699f357" data-id="dcfac1eb196f452b8076e62a5699f357"><span><div id="dcfac1eb196f452b8076e62a5699f357" class="notion-header-anchor"></div><a class="notion-hash-link" href="#dcfac1eb196f452b8076e62a5699f357" title="4.【路由器工作模式】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.【路由器工作模式】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-844eb6697ac1489b8f0e3861e54e38b0"><li><code class="notion-inline-code">history</code>模式</li><ol class="notion-list notion-list-numbered notion-block-844eb6697ac1489b8f0e3861e54e38b0"><div class="notion-text notion-block-38c1328706f04261956e2d1d74f5f01c">&gt; 优点：<code class="notion-inline-code">URL</code>更加美观，不带有<code class="notion-inline-code">#</code>，更接近传统的网站<code class="notion-inline-code">URL</code>。
&gt; 缺点：后期项目上线，需要服务端配合处理路径问题，否则刷新会有<code class="notion-inline-code">404</code>错误。</div></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-0ea387990223442898f1c0df5b1428ff"><li><code class="notion-inline-code">hash</code>模式</li><ol class="notion-list notion-list-numbered notion-block-0ea387990223442898f1c0df5b1428ff"><div class="notion-text notion-block-fe221ae51db34e60bd681ae4352f6108">&gt; 优点：兼容性更好，因为不需要服务器端处理路径。
&gt; 缺点：<code class="notion-inline-code">URL</code>带有<code class="notion-inline-code">#</code>不太美观，且在<code class="notion-inline-code">SEO</code>优化方面相对较差。</div></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-6e6fcc286be74a92a7c48246f17d32e5" data-id="6e6fcc286be74a92a7c48246f17d32e5"><span><div id="6e6fcc286be74a92a7c48246f17d32e5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#6e6fcc286be74a92a7c48246f17d32e5" title="5.【to的两种写法】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>5.【to的两种写法】</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-5dc1323fd051432abac8871cce40c25a" data-id="5dc1323fd051432abac8871cce40c25a"><span><div id="5dc1323fd051432abac8871cce40c25a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5dc1323fd051432abac8871cce40c25a" title="6.【命名路由】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>6.【命名路由】</b></span></span></h4><div class="notion-text notion-block-c94040d6eec8433aa31f7c4d9f68ffc2">给路由规则命名：</div><div class="notion-text notion-block-558756d647414340acbb1af2b7feae44">跳转路由：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ab1a3cf54a1b493ea9784078c28dff46" data-id="ab1a3cf54a1b493ea9784078c28dff46"><span><div id="ab1a3cf54a1b493ea9784078c28dff46" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ab1a3cf54a1b493ea9784078c28dff46" title="7.【嵌套路由】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>7.【嵌套路由】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-5e8557078fe34ab4a563c04b81b8dc47"><li>编写<code class="notion-inline-code">News</code>的子路由：<code class="notion-inline-code">Detail.vue</code></li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-f5b6beaa60d34d399bf25b8524030993"><li>配置路由规则，使用<code class="notion-inline-code">children</code>配置项：</li><ol class="notion-list notion-list-numbered notion-block-f5b6beaa60d34d399bf25b8524030993"></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-702dfee322e24deea84cd57628f07ea0"><li>跳转路由（记得要加完整路径）：</li><ol class="notion-list notion-list-numbered notion-block-702dfee322e24deea84cd57628f07ea0"></ol></ol><ol start="4" class="notion-list notion-list-numbered notion-block-7af3d93d667e4ce483c17083e28badd6"><li>记得去<code class="notion-inline-code">Home</code>组件中预留一个<code class="notion-inline-code">&lt;router-view&gt;</code></li><ol class="notion-list notion-list-numbered notion-block-7af3d93d667e4ce483c17083e28badd6"></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1a881285218a4979a7d936fad09c5835" data-id="1a881285218a4979a7d936fad09c5835"><span><div id="1a881285218a4979a7d936fad09c5835" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1a881285218a4979a7d936fad09c5835" title="8.【路由传参(URL参数)】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>8.【路由传参(URL参数)】</b></span></span></h4><div class="notion-text notion-block-a8f16a808939467d99f2271b5391bae9"><b>query参数（查询参数）</b>
query参数必须是key=value的形式，多种keyvalue之间还需要一个&amp;做衔接</div><div class="notion-text notion-block-44cd298491bd4b5bb246169f21e96d2f">1.传递参数：</div><div class="notion-text notion-block-fafeb482c0704bb18519671d627806ac">2.接收参数：</div><div class="notion-text notion-block-40235897ce8d45ea9f71d8c4f499d269"><b>params参数（路径参数）</b>
可以直接写/，但是必须在index.ts规则中占好位，在最后加上？就是配置参数的必要性。可传参可不传
传参时路径不能用path了，只能用name</div><div class="notion-text notion-block-ae1045b3a7c9478c9c46fd16582ebd5b">1.传递参数：</div><div class="notion-text notion-block-cf0500c49e8943368caff765f433af5b">2.接收参数：</div><div class="notion-text notion-block-7b4961d5c7154de5a2f25cba9a07a9c6">&gt; 备注1：传递<code class="notion-inline-code">params</code>参数时，若使用<code class="notion-inline-code">to</code>的对象写法，必须使用<code class="notion-inline-code">name</code>配置项，不能用<code class="notion-inline-code">path</code>。
&gt; 备注2：传递<code class="notion-inline-code">params</code>参数时，需要提前在规则中占位。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-dd689df5e3f34cd68d6591e57f822080" data-id="dd689df5e3f34cd68d6591e57f822080"><span><div id="dd689df5e3f34cd68d6591e57f822080" class="notion-header-anchor"></div><a class="notion-hash-link" href="#dd689df5e3f34cd68d6591e57f822080" title="9.【路由的props配置】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>9.【路由的props配置】</b></span></span></h4><div class="notion-text notion-block-7f975b903cfa4453bf4df6381bfce055">作用：让路由组件更方便的收到参数（可以将路由参数作为<code class="notion-inline-code">props</code>传给组件）</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-4d2346abd96844f294cd7242ba8b7593" data-id="4d2346abd96844f294cd7242ba8b7593"><span><div id="4d2346abd96844f294cd7242ba8b7593" class="notion-header-anchor"></div><a class="notion-hash-link" href="#4d2346abd96844f294cd7242ba8b7593" title="10.【 replace属性】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>10.【 replace属性】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-a545a42f746344489972391bad5e18a4"><li>作用：控制路由跳转时操作浏览器历史记录的模式。（在历史记录中返回不去）</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-02ec9135be38454b96bae4bf22cef51d"><li>浏览器的历史记录有两种写入方式：分别为<code class="notion-inline-code">push</code>和<code class="notion-inline-code">replace</code>：</li><ol class="notion-list notion-list-numbered notion-block-02ec9135be38454b96bae4bf22cef51d"><ul class="notion-list notion-list-disc notion-block-0abd94f901d94d83a0b5472b6e0145ce"><li><code class="notion-inline-code">push</code>是追加历史记录（默认值）。</li></ul><ul class="notion-list notion-list-disc notion-block-9cd024be72e342f1bc9fb78fa8c4a1b1"><li><code class="notion-inline-code">replace</code>是替换当前记录。</li></ul></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-8c79192f2ea14048aabe0083f12b0522"><li>开启<code class="notion-inline-code">replace</code>模式：
&lt;RouterLink replace .......&gt;News&lt;/RouterLink&gt;</li></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-f5443029e8304d768176e88a2d48e2ea" data-id="f5443029e8304d768176e88a2d48e2ea"><span><div id="f5443029e8304d768176e88a2d48e2ea" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f5443029e8304d768176e88a2d48e2ea" title="11.【编程式导航】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>11.【编程式导航】</b></span></span></h4><div class="notion-text notion-block-00d74023c514455eaac8c4dafcda77f6">脱离RouterLink实现路由跳转
使用场景：</div><ol start="1" class="notion-list notion-list-numbered notion-block-f32f42dbcee548d9ad148e3eb4939220"><li>只有符合某些条件再跳转，不是用户一点就跳转，到了时间自动跳，只有登陆成功，跳转到个人中心等</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-69be2e4073284c8c92e43666b4da406c"><li>鼠标滑过一个东西再跳转</li></ol><div class="notion-text notion-block-74a157a5b1c64ea4899be3f7103835fe">路由组件的两个重要的属性：<code class="notion-inline-code">$route</code>和<code class="notion-inline-code">$router</code>变成了两个<code class="notion-inline-code">hooks</code></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7be22f9d9a52426c87df3c14d6f7bec8" data-id="7be22f9d9a52426c87df3c14d6f7bec8"><span><div id="7be22f9d9a52426c87df3c14d6f7bec8" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7be22f9d9a52426c87df3c14d6f7bec8" title="12.【重定向】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.【重定向】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-c6411b57fe4d4459bb4b2fcde1d3ae60"><li>作用：将特定的路径，重新定向到已有路由。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-0da90e93b07f4da0a2c624e20c171348"><li>代码（在规则里直接加）：</li><ol class="notion-list notion-list-numbered notion-block-0da90e93b07f4da0a2c624e20c171348"></ol></ol><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-1346dde059bb440ebbe683ad57a7ad45" data-id="1346dde059bb440ebbe683ad57a7ad45"><span><div id="1346dde059bb440ebbe683ad57a7ad45" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1346dde059bb440ebbe683ad57a7ad45" title="pinia"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>pinia</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-8a442d8953d241d0a18d9eb26f9bd6e5" data-id="8a442d8953d241d0a18d9eb26f9bd6e5"><span><div id="8a442d8953d241d0a18d9eb26f9bd6e5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8a442d8953d241d0a18d9eb26f9bd6e5" title="1.【准备一个效果】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1.【准备一个效果】</b></span></span></h4><div class="notion-text notion-block-39678e4e704444f793251c8d86a7b146">vue2中用的是vuex，vue3用的是pinia。就是集中式状态管理</div><div class="notion-text notion-block-8c5a9ed19a5d44f59695ffee43a33257">hooks 只是把代码集中在一起，pinia是各个组件之间共享数据</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-990544c5d3684514904c56e29508ed96" data-id="990544c5d3684514904c56e29508ed96"><span><div id="990544c5d3684514904c56e29508ed96" class="notion-header-anchor"></div><a class="notion-hash-link" href="#990544c5d3684514904c56e29508ed96" title="2.【搭建 pinia 环境】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.【搭建 pinia 环境】</b></span></span></h4><div class="notion-text notion-block-105a638bce1942acb0f2dc2d67bc06c2">第一步：<code class="notion-inline-code">npm i pinia</code></div><div class="notion-text notion-block-5fb5e2a5c35a4a9882d44100aa9b7040">第二步：操作<code class="notion-inline-code">src/main.ts</code></div><div class="notion-text notion-block-45288c52f6234cffa788cbff11fb47bb">此时开发者工具中已经有了<code class="notion-inline-code">pinia</code>选项</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-03812b4beb4d4db08d1d21b90f38cb66" data-id="03812b4beb4d4db08d1d21b90f38cb66"><span><div id="03812b4beb4d4db08d1d21b90f38cb66" class="notion-header-anchor"></div><a class="notion-hash-link" href="#03812b4beb4d4db08d1d21b90f38cb66" title="3.【存储+读取数据】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>3.【存储+读取数据】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-441b4c8a7aac4ce098464d25e86276d6"><li><code class="notion-inline-code">Store</code>是一个保存：状态、业务逻辑 的实体，每个组件都可以读取、写入它。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-12757fb18c64491eaa7d9b1a936416e5"><li>它有三个概念：<code class="notion-inline-code">state</code>、<code class="notion-inline-code">getter</code>、<code class="notion-inline-code">action</code>，相当于组件中的： <code class="notion-inline-code">data</code>、 <code class="notion-inline-code">computed</code> 和 <code class="notion-inline-code">methods</code>。</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-2eaf17eb29204a8ab3a1b676e18fa564"><li>具体编码：<code class="notion-inline-code">src/store/count.ts</code></li><ol class="notion-list notion-list-numbered notion-block-2eaf17eb29204a8ab3a1b676e18fa564"></ol></ol><ol start="4" class="notion-list notion-list-numbered notion-block-3aa84f9672c9400db593af41f1a340b5"><li>具体编码：<code class="notion-inline-code">src/store/talk.ts</code></li><ol class="notion-list notion-list-numbered notion-block-3aa84f9672c9400db593af41f1a340b5"></ol></ol><ol start="5" class="notion-list notion-list-numbered notion-block-e12410fa31354a45b8fb72d6014c78ad"><li>组件中使用<code class="notion-inline-code">state</code>中的数据</li><ol class="notion-list notion-list-numbered notion-block-e12410fa31354a45b8fb72d6014c78ad"></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-eb8e4a3971044b479045dc68efd73340" data-id="eb8e4a3971044b479045dc68efd73340"><span><div id="eb8e4a3971044b479045dc68efd73340" class="notion-header-anchor"></div><a class="notion-hash-link" href="#eb8e4a3971044b479045dc68efd73340" title="4.【修改数据】(三种方式)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.【修改数据】(三种方式)</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-a7a9b2d8630240969db577bde65d17b0"><li>第一种修改方式，直接修改（与vue2不同，pinia可以直接修改）</li><ol class="notion-list notion-list-numbered notion-block-a7a9b2d8630240969db577bde65d17b0"></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-a20dd3dfa2ab42a0a7dde548ac7bfb6a"><li>第二种修改方式：批量修改</li><ol class="notion-list notion-list-numbered notion-block-a20dd3dfa2ab42a0a7dde548ac7bfb6a"></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-bfcbe279277c431696160a5f279ec828"><li>第三种修改方式：借助<code class="notion-inline-code">action</code>修改（<code class="notion-inline-code">action</code>中可以编写一些业务逻辑）</li><ol class="notion-list notion-list-numbered notion-block-bfcbe279277c431696160a5f279ec828"></ol></ol><ol start="4" class="notion-list notion-list-numbered notion-block-bb9abbeb824a4bb9811a7ed672bbdaef"><li>组件中调用<code class="notion-inline-code">action</code>即可</li><ol class="notion-list notion-list-numbered notion-block-bb9abbeb824a4bb9811a7ed672bbdaef"></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-4bdbe9b07bcd43ba8a2f26b4bf80cba9" data-id="4bdbe9b07bcd43ba8a2f26b4bf80cba9"><span><div id="4bdbe9b07bcd43ba8a2f26b4bf80cba9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#4bdbe9b07bcd43ba8a2f26b4bf80cba9" title="5.【storeToRefs】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>5.【storeToRefs】</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-9dee0f3326834757955804c7c60ea787"><li>借助<code class="notion-inline-code">storeToRefs</code>将<code class="notion-inline-code">store</code>中的数据转为<code class="notion-inline-code">ref</code>对象，方便在模板中使用。
- 注意：<code class="notion-inline-code">pinia</code>提供的<code class="notion-inline-code">storeToRefs</code>只会将数据做转换，而不关注’store’里的方法。而<code class="notion-inline-code">Vue</code>的<code class="notion-inline-code">toRefs</code>会转换<code class="notion-inline-code">store</code>中的所有数据包括方法。</li></ul><div class="notion-text notion-block-4adea70f72744a7f943f8697c4d7d815">直接解构赋值的话会丢失响应式。</div><div class="notion-text notion-block-f87d64ead83849928ffb5263d30887fd">用torefs包裹的话，会把store中所有的数据和方法都转化为ref</div><div class="notion-text notion-block-be87315a3ea0419abe19854fd9830605"><code class="notion-inline-code">pinia</code>提供的<code class="notion-inline-code">`storeToRefs</code>只会将数据做转换，而不关注<code class="notion-inline-code">store</code>里的方法</div><div class="notion-text notion-block-27e8a35cef054aa0a7a0b8a90b460144"><b>示例代码：</b></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-8a8ff503df61476ab77c63d0dbb7c78e" data-id="8a8ff503df61476ab77c63d0dbb7c78e"><span><div id="8a8ff503df61476ab77c63d0dbb7c78e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8a8ff503df61476ab77c63d0dbb7c78e" title="6.【getters】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>6.【getters】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-b3868c14e98b41d29ec12598ed0aae61"><li>概念：当<code class="notion-inline-code">state</code>中的数据，需要经过处理后再使用时，可以使用<code class="notion-inline-code">getters</code>配置。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-c83d7c0923244a438bfea9b861eacfde"><li>追加<code class="notion-inline-code">getters</code>配置。</li><ol class="notion-list notion-list-numbered notion-block-c83d7c0923244a438bfea9b861eacfde"></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-e58111c6b3e64723aeeb439f994b607b"><li>组件中读取数据：</li><ol class="notion-list notion-list-numbered notion-block-e58111c6b3e64723aeeb439f994b607b"></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-c070bfe4b5834e08b25e5a92f308a40b" data-id="c070bfe4b5834e08b25e5a92f308a40b"><span><div id="c070bfe4b5834e08b25e5a92f308a40b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c070bfe4b5834e08b25e5a92f308a40b" title="7.【$subscribe】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>7.【$subscribe】</b></span></span></h4><div class="notion-text notion-block-f814c052de194a4983696412962524f2">通过 store 的 <code class="notion-inline-code">$subscribe()</code> 方法侦听 <code class="notion-inline-code">state</code> 及其变化</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-5a7a0dcd06504ee3bb5b0d8803e0b4c0" data-id="5a7a0dcd06504ee3bb5b0d8803e0b4c0"><span><div id="5a7a0dcd06504ee3bb5b0d8803e0b4c0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5a7a0dcd06504ee3bb5b0d8803e0b4c0" title="8.【store组合式写法】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>8.【store组合式写法】</b></span></span></h4><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-dbf9b737c7014576979086e138ed729b" data-id="dbf9b737c7014576979086e138ed729b"><span><div id="dbf9b737c7014576979086e138ed729b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#dbf9b737c7014576979086e138ed729b" title="组件通信"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>组件通信</b></span></span></h3><div class="notion-text notion-block-2d191f2eb6a545c78ca7dad1cc627409"><code class="notion-inline-code">Vue3</code>组件通信和<code class="notion-inline-code">Vue2</code>的区别：</div><ul class="notion-list notion-list-disc notion-block-d79c527aab1946619ec92d7337992f92"><li>移出事件总线，使用<code class="notion-inline-code">mitt</code>代替。</li></ul><ul class="notion-list notion-list-disc notion-block-21f711f13f0b40929d5de305a5350ddf"><li><code class="notion-inline-code">vuex</code>换成了<code class="notion-inline-code">pinia</code>。</li></ul><ul class="notion-list notion-list-disc notion-block-795ef116062945d9b3d42933ac88c1c0"><li>把<code class="notion-inline-code">.sync</code>优化到了<code class="notion-inline-code">v-model</code>里面了。</li></ul><ul class="notion-list notion-list-disc notion-block-62c59e0f0df54864ace2317a161174c9"><li>把<code class="notion-inline-code">$listeners</code>所有的东西，合并到<code class="notion-inline-code">$attrs</code>中了。</li></ul><ul class="notion-list notion-list-disc notion-block-5041b688cb984e658beb6a1ef488dd62"><li><code class="notion-inline-code">$children</code>被砍掉了。</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2cf31bb6b47c41679ce282b457e43014" data-id="2cf31bb6b47c41679ce282b457e43014"><span><div id="2cf31bb6b47c41679ce282b457e43014" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2cf31bb6b47c41679ce282b457e43014" title="1.【props】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1.【props】</b></span></span></h4><div class="notion-text notion-block-1490f1e607d44cbb810714d1ed3caed2">概述：<code class="notion-inline-code">props</code>是使用频率最高的一种通信方式，常用与 ：父 ↔ 子。</div><ul class="notion-list notion-list-disc notion-block-9d75f0a6e33143a99a84b87439d68008"><li>若 父传子：属性值是非函数。</li></ul><ul class="notion-list notion-list-disc notion-block-cdc79b5e3a3d49e9b478bd2f0c4e5c07"><li>若 子传父：属性值是函数。</li></ul><div class="notion-text notion-block-682fca8222554ebfb94f1742ef55eb0d">父组件：</div><div class="notion-text notion-block-07934c8989d344ebb31a42f05ca50f24">子组件：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-3ce19e6365354ffc81c20235ae119fb9" data-id="3ce19e6365354ffc81c20235ae119fb9"><span><div id="3ce19e6365354ffc81c20235ae119fb9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3ce19e6365354ffc81c20235ae119fb9" title="2.【自定义事件】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.【自定义事件】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-0acbc13d2c0642ef9b7ed9624a23b013"><li>概述：自定义事件常用于：子 =&gt; 父。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-f57cebd9ed2947f4974b882784ccfea6"><li>注意区分好：原生事件、自定义事件。</li><ol class="notion-list notion-list-numbered notion-block-f57cebd9ed2947f4974b882784ccfea6"><ul class="notion-list notion-list-disc notion-block-a859ae77fa6646f3b762b5e825da5afd"><li>原生事件：</li><ul class="notion-list notion-list-disc notion-block-a859ae77fa6646f3b762b5e825da5afd"><li>事件名是特定的（<code class="notion-inline-code">click</code>、<code class="notion-inline-code">mosueenter</code>等等）</li><li>事件对象<code class="notion-inline-code">$event</code>: 是包含事件相关信息的对象（<code class="notion-inline-code">pageX</code>、<code class="notion-inline-code">pageY</code>、<code class="notion-inline-code">target</code>、<code class="notion-inline-code">keyCode</code>）</li></ul></ul><ul class="notion-list notion-list-disc notion-block-7c21066d98b44d33b1fb8cf4873208e1"><li>自定义事件：</li><ul class="notion-list notion-list-disc notion-block-7c21066d98b44d33b1fb8cf4873208e1"><li>事件名是任意名称</li><li><b>事件对象</b><code class="notion-inline-code"><b>$event</b></code><b>: 是调用</b><code class="notion-inline-code"><b>emit</b></code><b>时所提供的数据，可以是任意类型！！！</b></li></ul></ul></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-337bb7c33d814429a09b7b0d73c9bd6b"><li>示例：</li><ol class="notion-list notion-list-numbered notion-block-337bb7c33d814429a09b7b0d73c9bd6b"></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ccc59fc834524d98b1f22acca83b6a91" data-id="ccc59fc834524d98b1f22acca83b6a91"><span><div id="ccc59fc834524d98b1f22acca83b6a91" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ccc59fc834524d98b1f22acca83b6a91" title="3.【mitt】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>3.【mitt】</b></span></span></h4><div class="notion-text notion-block-e8f7fb16a82749b091d6c5de0ae90935">概述：与消息订阅与发布（<code class="notion-inline-code">pubsub</code>）功能类似，可以实现任意组件间通信。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-c75d5962cb244e62b2d3985c06b3aa54"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F2c930dfe-da21-46e5-a4f5-114f9750f2d0%2F8509fa75-6e1a-4540-9eff-8b9ce614df1a%2Fmitt.png?table=block&amp;id=c75d5962-cb24-4e62-b2d3-985c06b3aa54&amp;t=c75d5962-cb24-4e62-b2d3-985c06b3aa54&amp;width=882&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-4f32ed1eaa5549a3bca6a3089f578fc1">安装<code class="notion-inline-code">mitt</code></div><ol start="1" class="notion-list notion-list-numbered notion-block-8f9769ab2e8d4280a2debfff0ab85fce"><li>新建文件：<code class="notion-inline-code">src\utils\emitter.ts</code></li><ol class="notion-list notion-list-numbered notion-block-8f9769ab2e8d4280a2debfff0ab85fce"></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-446b622a993f49ab96baa2f6c6eeeb81"><li>接收数据的组件中：绑定事件、同时在销毁前解绑事件：</li><ol class="notion-list notion-list-numbered notion-block-446b622a993f49ab96baa2f6c6eeeb81"></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-5ae8d15d6a4c47beb0ea667656764066"><li>提供数据的组件，在合适的时候触发事件</li><ol class="notion-list notion-list-numbered notion-block-5ae8d15d6a4c47beb0ea667656764066"></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e5a94031873e499ba5bd7e6bb273b27b" data-id="e5a94031873e499ba5bd7e6bb273b27b"><span><div id="e5a94031873e499ba5bd7e6bb273b27b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e5a94031873e499ba5bd7e6bb273b27b" title="4.【v-model】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.【v-model】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-7dcf31cdd12347e7a4caf1555d279edf"><li>概述：实现 父↔子 之间相互通信。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-de9ab2768f1946b0b69088ceb19bc7d6"><li>前序知识 —— <code class="notion-inline-code">v-model</code>的本质</li><ol class="notion-list notion-list-numbered notion-block-de9ab2768f1946b0b69088ceb19bc7d6"></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-ced1f74fafea4f078ee58cfc88612614"><li>组件标签上的<code class="notion-inline-code">v-model</code>的本质：<code class="notion-inline-code">:moldeValue</code> ＋ <code class="notion-inline-code">update:modelValue</code>事件。</li><ol class="notion-list notion-list-numbered notion-block-ced1f74fafea4f078ee58cfc88612614"><div class="notion-text notion-block-890a216ffa20421db8faaa802f338fe4"><code class="notion-inline-code">AtguiguInput</code>组件中：</div></ol></ol><ol start="4" class="notion-list notion-list-numbered notion-block-3de3037e8d56449cb60639742a993269"><li>也可以更换<code class="notion-inline-code">value</code>，例如改成<code class="notion-inline-code">abc</code></li><ol class="notion-list notion-list-numbered notion-block-3de3037e8d56449cb60639742a993269"></ol></ol><ol start="5" class="notion-list notion-list-numbered notion-block-3f21e720c1944fc5b7bd73ae19a31faa"><li>如果<code class="notion-inline-code">value</code>可以更换，那么就可以在组件标签上多次使用<code class="notion-inline-code">v-model</code></li><ol class="notion-list notion-list-numbered notion-block-3f21e720c1944fc5b7bd73ae19a31faa"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-4b8a16d5aef544e48efb826d1d6ca10b"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F2c930dfe-da21-46e5-a4f5-114f9750f2d0%2Fda7c66d1-5d2e-48e7-ba42-cdd101d6bffb%2Fevent.png?table=block&amp;id=4b8a16d5-aef5-44e4-8efb-826d1d6ca10b&amp;t=4b8a16d5-aef5-44e4-8efb-826d1d6ca10b&amp;width=2382&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-0b9a537412664cd3b1926eed1b56b666" data-id="0b9a537412664cd3b1926eed1b56b666"><span><div id="0b9a537412664cd3b1926eed1b56b666" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0b9a537412664cd3b1926eed1b56b666" title="5.【$attrs 】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>5.【$attrs 】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-6955505cf8834a85b43fc0ee28b393ff"><li>概述：<code class="notion-inline-code">$attrs</code>用于实现当前组件的父组件（相当于一个中间人），向当前组件的子组件通信（祖→孙）。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-d0696015d8d544fe8b70eb76ba8fd37b"><li>具体说明：<code class="notion-inline-code">$attrs</code>是一个对象，包含所有父组件传入的标签属性。</li><ol class="notion-list notion-list-numbered notion-block-d0696015d8d544fe8b70eb76ba8fd37b"><blockquote class="notion-quote notion-block-ddb46e2c833448c2acf807ef6019ef73"><div>注意：$attrs会自动排除props中声明的属性(可以认为声明过的 props 被子组件自己“消费”了)</div></blockquote></ol></ol><div class="notion-text notion-block-3896c41aa26948dca104493444b20047">父组件：</div><div class="notion-text notion-block-feec5970d9f54f42859b1dd08f6340db">子组件：</div><div class="notion-text notion-block-ee26165b2ffc4966961c86b22318b8cb">孙组件：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-79fc3ad067be4a758d06fbcce6794a1f" data-id="79fc3ad067be4a758d06fbcce6794a1f"><span><div id="79fc3ad067be4a758d06fbcce6794a1f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#79fc3ad067be4a758d06fbcce6794a1f" title="6.【$refs、$parent】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>6.【$refs、$parent】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-91b9faac859f424b8aa0e1482ffb414c"><li>概述：</li><ol class="notion-list notion-list-numbered notion-block-91b9faac859f424b8aa0e1482ffb414c"><ul class="notion-list notion-list-disc notion-block-e59ff49e47b844cb94f173215a4157d4"><li><code class="notion-inline-code">$refs</code>用于 ：父→子。</li></ul><ul class="notion-list notion-list-disc notion-block-e33be8e16fc14af7b578a79794529a82"><li><code class="notion-inline-code">$parent</code>用于：子→父。</li></ul></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-ec0e5bd00000401bad55f323dc27b0ff"><li>原理如下：</li><ol class="notion-list notion-list-numbered notion-block-ec0e5bd00000401bad55f323dc27b0ff"><ul class="notion-list notion-list-disc notion-block-95ba414fe3884687bf527220599c3ad5"><li><code class="notion-inline-code">$refs</code> ：值为对象，包含所有被<code class="notion-inline-code">ref</code>属性标识的<code class="notion-inline-code">DOM</code>元素或组件实例。</li></ul><ul class="notion-list notion-list-disc notion-block-d1d55afbdf2d4cfba99de628264339ef"><li><code class="notion-inline-code">$parent</code>：值为对象，当前组件的父组件实例对象。</li></ul></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-51ca183f1a61484ba436df28552e43b2" data-id="51ca183f1a61484ba436df28552e43b2"><span><div id="51ca183f1a61484ba436df28552e43b2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#51ca183f1a61484ba436df28552e43b2" title="7.【provide、inject】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>7.【provide、inject】</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-ddbcae69acd04f5e8f1b748b1f1f5fcf"><li>概述：实现祖孙组件直接通信</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-af69c36ac82d4f44b4179b7b2a89a2cc"><li>具体使用：</li><ol class="notion-list notion-list-numbered notion-block-af69c36ac82d4f44b4179b7b2a89a2cc"><ul class="notion-list notion-list-disc notion-block-13146f09ca7c4edebcf2c8462f54490e"><li>在祖先组件中通过<code class="notion-inline-code">provide</code>配置向后代组件提供数据</li></ul><ul class="notion-list notion-list-disc notion-block-24c19099d6f14f6db1df6ee233a73859"><li>在后代组件中通过<code class="notion-inline-code">inject</code>配置来声明接收数据</li></ul></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-c6a22ab7edf34ea89063c207a450f870"><li>具体编码：</li><ol class="notion-list notion-list-numbered notion-block-c6a22ab7edf34ea89063c207a450f870"><div class="notion-text notion-block-949e22332b5147d38f71e67f7b797fbd">【<b>第一步</b>】父组件中，使用<code class="notion-inline-code">provide</code>提供数据</div><blockquote class="notion-quote notion-block-f1ac1855b9594dfcba0f377831d55bae"><div>注意：子组件中不用编写任何东西，是不受到任何打扰的</div></blockquote><div class="notion-text notion-block-9dc2c3dfe9f247a38ddd0bcd19e41407">【<b>第二步</b>】孙组件中使用<code class="notion-inline-code">inject</code>配置项接受数据。</div></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-a5aa7b1627a34987a15f8d1c05e49b6f" data-id="a5aa7b1627a34987a15f8d1c05e49b6f"><span><div id="a5aa7b1627a34987a15f8d1c05e49b6f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a5aa7b1627a34987a15f8d1c05e49b6f" title="8.【pinia】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>8.【pinia】</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-d9ea9a46c79f401289a6b73242ba4388" data-id="d9ea9a46c79f401289a6b73242ba4388"><span><div id="d9ea9a46c79f401289a6b73242ba4388" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d9ea9a46c79f401289a6b73242ba4388" title="9.【slot】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>9.【slot】</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-81388c6d620742d8bc328e2e4332369c" data-id="81388c6d620742d8bc328e2e4332369c"><span><div id="81388c6d620742d8bc328e2e4332369c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#81388c6d620742d8bc328e2e4332369c" title="1.默认插槽"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1.默认插槽</b></span></span></h4><div class="notion-text notion-block-45f7dc3b723f408d80a4dab8bbbd20c0">就是在父组件中的子组件的双标签中写入标签，在子组件中需要的地方插入slot，子组件就会接收到父组件中传输过来的数据。</div><div class="notion-text notion-block-311a4c8fd1744ca6b2e85e4d2d5a7af3">子组件的插槽相当于一个“坑”，父组件的数据相当于“土”。如果在子组件中的插槽有几对，就会显示几次数据。</div><div class="notion-text notion-block-6d808936c65342b883b2c8f771ffdc16">默认插槽的name是name:dafault</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-460b5d317f344ca2b45be360c8dec81c" data-id="460b5d317f344ca2b45be360c8dec81c"><span><div id="460b5d317f344ca2b45be360c8dec81c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#460b5d317f344ca2b45be360c8dec81c" title="2.具名插槽"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.具名插槽</b></span></span></h4><div class="notion-text notion-block-f4bbe56a469b4a4fb3708c6267234813">在子组件中的插槽中给name，父组件中的name与子组件中插槽的name相同，会把数据插入到相同name的插槽中。简单来说，就是把数据插入到指定的位置</div><div class="notion-text notion-block-8d652c16060d48ddabbcf703ca04d56b">在父组件中的组件标签中写入template标签，把要插入子组件的数据放入到template标签中，给template标签name</div><div class="notion-text notion-block-dfe034941cac4620b978f039100c5093"><code class="notion-inline-code">父组件中：</code></div><div class="notion-text notion-block-72e3d66c345b48b997fcf5555ff27722"><code class="notion-inline-code">子组件中：</code></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e036547c9f954db1aaac90c0347021cf" data-id="e036547c9f954db1aaac90c0347021cf"><span><div id="e036547c9f954db1aaac90c0347021cf" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e036547c9f954db1aaac90c0347021cf" title="3.作用域插槽"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>3.作用域插槽</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-0a04103725984459bf12552881f8155c"><li>理解：数据在组件的自身，但根据数据生成的结构需要组件的使用者来决定。（新闻数据在<code class="notion-inline-code">News</code>组件中，但使用数据所遍历出来的结构由<code class="notion-inline-code">App</code>组件决定）</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-a88492f2c4584958adbdd685eebdb886"><li>作用于插槽也有name</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-651ced92b684485eb34f440eec8c4f53"><li>具体编码：</li><ol class="notion-list notion-list-numbered notion-block-651ced92b684485eb34f440eec8c4f53"><div class="notion-text notion-block-58d9c556bb3847378d0fd593e97f43b1"><code class="notion-inline-code">父组件中：</code></div><div class="notion-text notion-block-0b672a2b7dea4f27a3f69a09a912f1cd"><code class="notion-inline-code">子组件中：</code></div></ol></ol><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-1f7fe0dd1b724df5b79460670867debd" data-id="1f7fe0dd1b724df5b79460670867debd"><span><div id="1f7fe0dd1b724df5b79460670867debd" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1f7fe0dd1b724df5b79460670867debd" title="其它 API"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>其它 API</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-32621518216f45aaa0b71bdc688939e9" data-id="32621518216f45aaa0b71bdc688939e9"><span><div id="32621518216f45aaa0b71bdc688939e9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#32621518216f45aaa0b71bdc688939e9" title="1.【shallowRef 与 shallowReactive 】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1.【shallowRef 与 shallowReactive 】</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-bbdfb6886d78454985f17de6215692e1" data-id="bbdfb6886d78454985f17de6215692e1"><span><div id="bbdfb6886d78454985f17de6215692e1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#bbdfb6886d78454985f17de6215692e1" title="shallowRef"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>shallowRef</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-2e923b6c859d4f6e99b29362d5a6a1d3"><li>作用：创建一个响应式数据，但只对顶层属性进行响应式处理。只能处理第一层的数据。如person.value.name,这就属于二层数据。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-1e01a68437d842bfbe0bcb5bfcd8ffc0"><li>用法：</li><ol class="notion-list notion-list-numbered notion-block-1e01a68437d842bfbe0bcb5bfcd8ffc0"></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-3d37fc330f4d45ed8ca2214039c3e979"><li>特点：只跟踪引用值的变化，不关心值内部的属性变化。</li></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-17aeba1c5fe046c2ae0056b00c1b2eb0" data-id="17aeba1c5fe046c2ae0056b00c1b2eb0"><span><div id="17aeba1c5fe046c2ae0056b00c1b2eb0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#17aeba1c5fe046c2ae0056b00c1b2eb0" title="shallowReactive"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>shallowReactive</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-24438460b2aa4250869f48c0302f086b"><li>作用：创建一个浅层响应式对象，只会使对象的最顶层属性变成响应式的，对象内部的嵌套属性则不会变成响应式的</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-e7b6aefcac92497f97eb5d18ab55e379"><li>用法：</li><ol class="notion-list notion-list-numbered notion-block-e7b6aefcac92497f97eb5d18ab55e379"></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-484f00a1ba34491dbe1e5a8050d7be5a"><li>特点：对象的顶层属性是响应式的，但嵌套对象的属性不是。</li></ol><div class="notion-text notion-block-a418c394653f449a9498b40b4f4319de">总结：</div><div class="notion-text notion-block-914ce381ea8344ca9abd04267a1a4545">通过使用<code class="notion-inline-code">shallowRef()</code>和<code class="notion-inline-code">shallowReactive()</code>  来绕开深度响应。<span class="notion-inline-underscore">浅层式</span> <code class="notion-inline-code">API</code> 创建的状态只在其顶层是<span class="notion-inline-underscore">响应式的</span>，对所有深层的对象不会做任何处理，避免了对每一个内部属性做响应式所带来的<span class="notion-inline-underscore">性能成本</span>，这使得属性的访问<span class="notion-inline-underscore">变得更快</span>，可提升性能。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e1c3f7aabf004fe2b9aca83dc1c1b6a1" data-id="e1c3f7aabf004fe2b9aca83dc1c1b6a1"><span><div id="e1c3f7aabf004fe2b9aca83dc1c1b6a1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e1c3f7aabf004fe2b9aca83dc1c1b6a1" title="2.【readonly 与 shallowReadonly】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.【readonly 与 shallowReadonly】</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-23dcbd71d0c24e4ea718294f1505a830" data-id="23dcbd71d0c24e4ea718294f1505a830"><span><div id="23dcbd71d0c24e4ea718294f1505a830" class="notion-header-anchor"></div><a class="notion-hash-link" href="#23dcbd71d0c24e4ea718294f1505a830" title="readonly"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>readonly</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-9c78a87c954148c8830eeb69e75d5d9f"><li>作用：用于创建一个对象的深只读副本。对数据进行保护，限制只有某人能修改等</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-4ec7c7d4d6e54f8eb9c844354130aed5"><li>用法：</li><ol class="notion-list notion-list-numbered notion-block-4ec7c7d4d6e54f8eb9c844354130aed5"></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-37ecf672e70b40da935e322b6923d3d9"><li>特点：</li><ol class="notion-list notion-list-numbered notion-block-37ecf672e70b40da935e322b6923d3d9"><ul class="notion-list notion-list-disc notion-block-fd1a9f42c72440919ba0bf9a17aa0bd0"><li>对象的所有嵌套属性都将变为只读。</li></ul><ul class="notion-list notion-list-disc notion-block-23b3c8e464ff45d7a9f9dd81e8369eb3"><li>任何尝试修改这个对象的操作都会被阻止（在开发模式下，还会在控制台中发出警告）。</li></ul></ol></ol><ol start="4" class="notion-list notion-list-numbered notion-block-d0f5c352fccd4be88248d588d52194cb"><li>应用场景：</li><ol class="notion-list notion-list-numbered notion-block-d0f5c352fccd4be88248d588d52194cb"><ul class="notion-list notion-list-disc notion-block-b9659add232645aa8991f8c2d3d360e2"><li>创建不可变的状态快照。</li></ul><ul class="notion-list notion-list-disc notion-block-dca126ee7adc4894b6c3a014461d2f5a"><li>保护全局状态或配置不被修改。</li></ul></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1705803fc4934b1d95059d25f6a699a4" data-id="1705803fc4934b1d95059d25f6a699a4"><span><div id="1705803fc4934b1d95059d25f6a699a4" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1705803fc4934b1d95059d25f6a699a4" title="shallowReadonly"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>shallowReadonly</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-1df457374fb04bd6b9ffdbfb0fac40f4"><li>作用：与 <code class="notion-inline-code">readonly</code> 类似，但只作用于对象的顶层属性。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-ee3a3844f079497d9f8a68ade9632ab3"><li>用法：</li><ol class="notion-list notion-list-numbered notion-block-ee3a3844f079497d9f8a68ade9632ab3"></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-9a9a29042dc440edaf8205377a912c20"><li>特点：</li><ol class="notion-list notion-list-numbered notion-block-9a9a29042dc440edaf8205377a912c20"><ul class="notion-list notion-list-disc notion-block-d9a383f0870c48079e0813c77842241a"><li>只将对象的顶层属性设置为只读，对象内部的嵌套属性仍然是可变的。只限制第一层数据，内层数据不限制</li></ul><ul class="notion-list notion-list-disc notion-block-e6ee5178911e4b928e9c89efdbaba9f5"><li>适用于只需保护对象顶层属性的场景。</li></ul></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1cacf05f4e7c471a909b502f1d2311cb" data-id="1cacf05f4e7c471a909b502f1d2311cb"><span><div id="1cacf05f4e7c471a909b502f1d2311cb" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1cacf05f4e7c471a909b502f1d2311cb" title="3.【toRaw 与 markRaw】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>3.【toRaw 与 markRaw】</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-411e0ff5f42e46d9bb4354c1dbdf7d48" data-id="411e0ff5f42e46d9bb4354c1dbdf7d48"><span><div id="411e0ff5f42e46d9bb4354c1dbdf7d48" class="notion-header-anchor"></div><a class="notion-hash-link" href="#411e0ff5f42e46d9bb4354c1dbdf7d48" title="toRaw"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>toRaw</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-6bd1c930b3a44a6c99297091764fe79f"><li>作用：用于获取一个响应式对象的原始对象， <code class="notion-inline-code">toRaw</code> 返回的对象不再是响应式的，不会触发视图更新。</li><ol class="notion-list notion-list-numbered notion-block-6bd1c930b3a44a6c99297091764fe79f"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a93aacf72e845168d1da5eea79478d1"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F2c930dfe-da21-46e5-a4f5-114f9750f2d0%2F356dba0c-1d47-4eea-aed5-898cce85fdbe%2FtoRaw.png?table=block&amp;id=2a93aacf-72e8-4516-8d1d-a5eea79478d1&amp;t=2a93aacf-72e8-4516-8d1d-a5eea79478d1&amp;width=2396&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-b3b2855cfa844501b2a6e2eb8132e076"><li>具体编码：</li><ol class="notion-list notion-list-numbered notion-block-b3b2855cfa844501b2a6e2eb8132e076"></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-903960ce34f24392a4ac8e4beb168b4e" data-id="903960ce34f24392a4ac8e4beb168b4e"><span><div id="903960ce34f24392a4ac8e4beb168b4e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#903960ce34f24392a4ac8e4beb168b4e" title="markRaw"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>markRaw</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-13118efe76d14bb797b17992e0a3a16b"><li>作用：标记一个对象，使其永远不会变成响应式的。</li><ol class="notion-list notion-list-numbered notion-block-13118efe76d14bb797b17992e0a3a16b"><blockquote class="notion-quote notion-block-c25b5521c11748ce87d67ff8fdad08e2"><div>例如使用mockjs时，为了防止误把mockjs变为响应式对象，可以使用 markRaw 去标记mockjs</div></blockquote></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-4e258350a1074ed9981e1a6b853c955d"><li>编码：</li><ol class="notion-list notion-list-numbered notion-block-4e258350a1074ed9981e1a6b853c955d"></ol></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-567648bc9cdd42cd9e8feaaef1f1b235" data-id="567648bc9cdd42cd9e8feaaef1f1b235"><span><div id="567648bc9cdd42cd9e8feaaef1f1b235" class="notion-header-anchor"></div><a class="notion-hash-link" href="#567648bc9cdd42cd9e8feaaef1f1b235" title="4.【customRef】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.【customRef】</b></span></span></h4><div class="notion-text notion-block-317d7f4c58ad41679264f26ec988eda7">作用：创建一个自定义的<code class="notion-inline-code">ref</code>，并对其依赖项跟踪和更新触发进行逻辑控制。</div><div class="notion-text notion-block-c8ac28ff5cf14749a178c59cd491518a">实现防抖效果（<code class="notion-inline-code">useSumRef.ts</code>）：</div><div class="notion-text notion-block-cd9b2c483027475985ce1628d038635c">组件中：</div><div class="notion-text notion-block-d1708c933c5c4a6d9cdf98838a6fa200">注意：customRef中最核心的就是track和trigger，track是持续跟踪，trigger是通知你完成了。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-b9bdae89f6e14474847d50ba75c1f629" data-id="b9bdae89f6e14474847d50ba75c1f629"><span><div id="b9bdae89f6e14474847d50ba75c1f629" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b9bdae89f6e14474847d50ba75c1f629" title="Vue3新组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Vue3新组件</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-67406877bc1a49448624fd79305a4af0" data-id="67406877bc1a49448624fd79305a4af0"><span><div id="67406877bc1a49448624fd79305a4af0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#67406877bc1a49448624fd79305a4af0" title="1.【Teleport】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1.【Teleport】</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-17b41882e9ca4737a7f1a0f6012f8d31"><li>什么是Teleport？—— Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-a132023ac40544939e65dabfd5a2641b" data-id="a132023ac40544939e65dabfd5a2641b"><span><div id="a132023ac40544939e65dabfd5a2641b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a132023ac40544939e65dabfd5a2641b" title="2.【Suspense】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.【Suspense】</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-974cb3e226024a278bc67635fcc7c6ea"><li>等待异步组件时渲染一些额外内容，让应用有更好的用户体验
- 使用步骤： - 异步引入组件 - 使用<code class="notion-inline-code">Suspense</code>包裹组件，并配置好<code class="notion-inline-code">default</code> 与 <code class="notion-inline-code">fallback</code></li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ef804ce926114dfbb6c2d072b576f703" data-id="ef804ce926114dfbb6c2d072b576f703"><span><div id="ef804ce926114dfbb6c2d072b576f703" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ef804ce926114dfbb6c2d072b576f703" title="3.【全局API转移到应用对象】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>3.【全局API转移到应用对象】</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-108e7c8dea56415baf38428396cecabb"><li><code class="notion-inline-code">app.component</code>
- <code class="notion-inline-code">app.config</code>
- <code class="notion-inline-code">app.directive</code>
- <code class="notion-inline-code">app.mount</code>
- <code class="notion-inline-code">app.unmount</code>
- <code class="notion-inline-code">app.use</code></li></ul><div class="notion-text notion-block-8f9c7b27b3384edd9be29aa8abc0d8f1">就是将vue2中原来是Vue.xxx的改成app.xxx</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-471bca818abc4aa8992fe5aab72748cb" data-id="471bca818abc4aa8992fe5aab72748cb"><span><div id="471bca818abc4aa8992fe5aab72748cb" class="notion-header-anchor"></div><a class="notion-hash-link" href="#471bca818abc4aa8992fe5aab72748cb" title="4.【其他】"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.【其他】</b></span></span></h4><div class="notion-text notion-block-704d736629aa413cac2d9f5acfc4d8e7">（干开发的最好去官网看看vue3中的非兼容性改变，面试问）</div><ul class="notion-list notion-list-disc notion-block-2f789e135324415c8f332d6ba929951e"><li>过渡类名 <code class="notion-inline-code">v-enter</code> 修改为 <code class="notion-inline-code">v-enter-from</code>、过渡类名 <code class="notion-inline-code">v-leave</code> 修改为 <code class="notion-inline-code">v-leave-from</code>。</li></ul><ul class="notion-list notion-list-disc notion-block-e1bd1b480bff4b04a3a303013affacac"><li><code class="notion-inline-code">keyCode</code> 作为 <code class="notion-inline-code">v-on</code> 修饰符的支持。</li></ul><ul class="notion-list notion-list-disc notion-block-0130855cb3064d8492ed9b456820b116"><li><code class="notion-inline-code">v-model</code> 指令在组件上的使用已经被重新设计，替换掉了 <code class="notion-inline-code">v-bind.sync。</code></li></ul><ul class="notion-list notion-list-disc notion-block-b62a78bc50dd40db96478b86b1c2a5ad"><li><code class="notion-inline-code">v-if</code> 和 <code class="notion-inline-code">v-for</code> 在同一个元素身上使用时的优先级发生了变化。</li></ul><ul class="notion-list notion-list-disc notion-block-27c1cf329a35458591b8103dd8a42c0a"><li>移除了<code class="notion-inline-code">$on</code>、<code class="notion-inline-code">$off</code> 和 <code class="notion-inline-code">$once</code> 实例方法。</li></ul><ul class="notion-list notion-list-disc notion-block-eba0dcac2ad14087bf85236d89297c0a"><li>移除了过滤器 <code class="notion-inline-code">filter</code>。</li></ul><ul class="notion-list notion-list-disc notion-block-e09e47e1ca114da09f0095dc774ef9a0"><li>移除了<code class="notion-inline-code">$children</code> 实例 <code class="notion-inline-code">propert</code>。</li></ul></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React笔记-Router]]></title>
            <link>https://www.axin.work/article/da005316-1867-4005-97f7-79a0df30cdf3</link>
            <guid>https://www.axin.work/article/da005316-1867-4005-97f7-79a0df30cdf3</guid>
            <pubDate>Fri, 31 May 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-da0053161867400597f779a0df30cdf3"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2a25ea4e839b4abba8118715c7f63f47" data-id="2a25ea4e839b4abba8118715c7f63f47"><span><div id="2a25ea4e839b4abba8118715c7f63f47" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a25ea4e839b4abba8118715c7f63f47" title="Router"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Router</b></span></span></h2><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-0847c5420f214043b54c5c2c065ae753" data-id="0847c5420f214043b54c5c2c065ae753"><span><div id="0847c5420f214043b54c5c2c065ae753" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0847c5420f214043b54c5c2c065ae753" title="详细使用示例"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>详细使用示例</b></span></span></h3><div class="notion-text notion-block-5e02503856e349238b8e2ca609d7a645">注意：这里使用的时最新的 v6 版本，已完全弃用了原先的 react-router 库，较 v5 版本有很大的改动。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-421f916f6f4f43769a0c43b890090509" data-id="421f916f6f4f43769a0c43b890090509"><span><div id="421f916f6f4f43769a0c43b890090509" class="notion-header-anchor"></div><a class="notion-hash-link" href="#421f916f6f4f43769a0c43b890090509" title="一、基本使用"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>一、基本使用</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-bcce7c0fed284af6b6f3f88dcf29cf53"><li>首先安装依赖</li></ol><ol start="1" class="notion-list notion-list-numbered notion-block-853ac971ad93475085b93f64556316c8"><li>引入实现路由所需的组件，以及页面组件</li></ol><ul class="notion-list notion-list-disc notion-block-55b1b2e6352b47d3a7daa1318a02ffac"><li><code class="notion-inline-code">path</code>：路径</li></ul><ul class="notion-list notion-list-disc notion-block-6eb8691700fa4973a5c6ff418ea97702"><li><code class="notion-inline-code">element</code>：要渲染的组件</li></ul><blockquote class="notion-quote notion-block-e295a374f7b44e72858809fc335cb8fe"><div>注意：BrowserRouter组件最好放在最顶层所有组件之外，这样能确保内部组件使用 Link 做路由跳转时不出错</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-3f32bccbc2bc4aa79c716757a9a5f57f" data-id="3f32bccbc2bc4aa79c716757a9a5f57f"><span><div id="3f32bccbc2bc4aa79c716757a9a5f57f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3f32bccbc2bc4aa79c716757a9a5f57f" title="二、路由跳转"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>二、路由跳转</b></span></span></h4><div class="notion-text notion-block-4a69e93d67a843c7809377cf791de56d">在跳转路由时，如果路径是<code class="notion-inline-code">/</code>开头的则是绝对路由，否则为<b>相对路由</b>，即<b>相对于当前 URL</b>进行改变</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-16792655c3884254930b38b65faf5d8d" data-id="16792655c3884254930b38b65faf5d8d"><span><div id="16792655c3884254930b38b65faf5d8d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#16792655c3884254930b38b65faf5d8d" title="2.1 Link 组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.1 Link 组件</b></span></span></h4><div class="notion-text notion-block-f0b6be3902804385b514eee799b0c6d8"><code class="notion-inline-code">Link组件</code>只能在<code class="notion-inline-code">Router</code>内部使用，因此使用到<code class="notion-inline-code">Link组件</code>的组件一定要放在顶层的 Router 之内</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-481358f59b4542b688ed2acf6cd75020" data-id="481358f59b4542b688ed2acf6cd75020"><span><div id="481358f59b4542b688ed2acf6cd75020" class="notion-header-anchor"></div><a class="notion-hash-link" href="#481358f59b4542b688ed2acf6cd75020" title="2.2 NavLink 组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.2 NavLink 组件</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-44fe2c83443a461a8b6661a7bc3942c8"><li><code class="notion-inline-code">NavLink组件</code>和<code class="notion-inline-code">Link组件</code>的功能是一致的，区别在于可以判断其<code class="notion-inline-code">to属性</code>是否是当前匹配到的路由</li></ul><ul class="notion-list notion-list-disc notion-block-c220a21cb6e5482e914875f295a8f156"><li><code class="notion-inline-code">NavLink组件</code>的<code class="notion-inline-code">style</code>或<code class="notion-inline-code">className</code>可以接收一个函数，函数接收一个含有<code class="notion-inline-code">isActive</code>字段的对象为参数，可根据该参数调整样式</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-020ff9f1d32a4e618d0e96f286b26b3b" data-id="020ff9f1d32a4e618d0e96f286b26b3b"><span><div id="020ff9f1d32a4e618d0e96f286b26b3b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#020ff9f1d32a4e618d0e96f286b26b3b" title="2.3 编程式跳转"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.3 编程式跳转</b></span></span></h4><div class="notion-text notion-block-aa7655f5d5f6464fbaca4b3bb48b0a59">使用<code class="notion-inline-code">useNavigate</code>钩子函数生成<code class="notion-inline-code">navigate函数</code>，可以通过 JS 代码完成路由跳转</div><blockquote class="notion-quote notion-block-5690e7ba470e44ac95be27a310c36823"><div>useNavigate`取代了原先版本中的`useHistory</div></blockquote><ul class="notion-list notion-list-disc notion-block-059b924aeedb45ec98c71053650ad32d"><li>可以直接传入要跳转的目标路由（可以使用相对路径，语法和 JS 相同）</li></ul><ul class="notion-list notion-list-disc notion-block-ede01cbea31b47059bacf5c36d5b2d31"><li>传入<code class="notion-inline-code">1</code>表示后退</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2419fd33b10c4253a419017131c7a12a" data-id="2419fd33b10c4253a419017131c7a12a"><span><div id="2419fd33b10c4253a419017131c7a12a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2419fd33b10c4253a419017131c7a12a" title="四、动态路由参数(URL参数)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>四、动态路由参数(URL参数)</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-a139263e712746e7a57b13f574374717" data-id="a139263e712746e7a57b13f574374717"><span><div id="a139263e712746e7a57b13f574374717" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a139263e712746e7a57b13f574374717" title="4.1 路径参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.1 路径参数</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-f77c9ab0600745adaec6e3c44d993f6c"><li>在<code class="notion-inline-code">Route组件</code>中的<code class="notion-inline-code">path属性</code>中定义路径参数</li></ul><ul class="notion-list notion-list-disc notion-block-d636d57dce014212827a55e3a9980c2e"><li>在组件内通过<code class="notion-inline-code">useParams</code> hook 访问路径参数</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7962ff933ada41a099439f6be87164f7" data-id="7962ff933ada41a099439f6be87164f7"><span><div id="7962ff933ada41a099439f6be87164f7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7962ff933ada41a099439f6be87164f7" title="路径匹配规则"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路径匹配规则</b></span></span></h4><div class="notion-text notion-block-1dfc1ec3d48649c98e6adfd3928d92ed">当URL同时匹配到含有路径参数的路径和无参数路径时，有限匹配没有参数的”具体的“（specific）路径。</div><div class="notion-text notion-block-34aae2bb1e3f4eae91241834c7aa768e">如上的两个路径，将会匹配 <code class="notion-inline-code">teams/new</code> 。</div><div class="notion-text notion-block-43891b173ddb46af8b4fd68a875f159f">路径的正则匹配已被移除。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-321fe8d0b75b420f9894f7c4e9a3b93d" data-id="321fe8d0b75b420f9894f7c4e9a3b93d"><span><div id="321fe8d0b75b420f9894f7c4e9a3b93d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#321fe8d0b75b420f9894f7c4e9a3b93d" title="兼容类组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>兼容类组件</b></span></span></h4><div class="notion-text notion-block-4ca2b14e501d47929178646ee1d94325">在以前版本中，组件的<code class="notion-inline-code">props</code>会包含一个<code class="notion-inline-code">match对象</code>，在其中可以取到路径参数。</div><div class="notion-text notion-block-666e8920c1f34ba3b80b452111438834">但在最新的 6.x 版本中，无法从 props 获取参数。</div><div class="notion-text notion-block-5a274cae437d4cb1abcdb0869b965db5">并且，针对类组件的 <code class="notion-inline-code">withRouter</code> 高阶组件已被移除。因此对于类组件来说，使用参数有两种兼容方法：</div><ol start="1" class="notion-list notion-list-numbered notion-block-d4d3bc01a7a94fcbbce1b2f5aaf848a6"><li>将类组件改写为函数组件</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-d8b86a97aad849878b6cc74fce17383f"><li>自己写一个 HOC 来包裹类组件，用 <code class="notion-inline-code">useParams</code> 获取参数后通过 props 传入原本的类组件</li></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ae8b96d8386a405b848211ca6e557e98" data-id="ae8b96d8386a405b848211ca6e557e98"><span><div id="ae8b96d8386a405b848211ca6e557e98" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ae8b96d8386a405b848211ca6e557e98" title="4.2 search 参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.2 search 参数</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-75eeab4952a647ba8db7c7ddde69433d"><li>查询参数不需要在路由中定义</li></ul><ul class="notion-list notion-list-disc notion-block-1b6e5f9d15164a96ba6d06667dca4f6b"><li>使用 <code class="notion-inline-code">useSearchParams</code> hook 来访问和修改查询参数。其用法和 <code class="notion-inline-code">useState</code> 类似，会返回当前对象和更改它的方法</li></ul><ul class="notion-list notion-list-disc notion-block-6c3ad9dd946a4ec5b48504e3e4218602"><li>使用 <code class="notion-inline-code">setSearchParams</code> 时，<b>必须传入所有的查询参数</b>，否则会覆盖已有参数</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-21e9a4b072d24348a72b57f0017e74b0" data-id="21e9a4b072d24348a72b57f0017e74b0"><span><div id="21e9a4b072d24348a72b57f0017e74b0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#21e9a4b072d24348a72b57f0017e74b0" title="五、嵌套路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>五、嵌套路由</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-6896692f12104be7872f96c4c782bb5d" data-id="6896692f12104be7872f96c4c782bb5d"><span><div id="6896692f12104be7872f96c4c782bb5d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#6896692f12104be7872f96c4c782bb5d" title="5.1 路由定义"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>5.1 路由定义</b></span></span></h4><div class="notion-text notion-block-c067b3489d154785b537a00636dc38b7">通过嵌套的书写<code class="notion-inline-code">Route组件</code>实现对嵌套路由的定义。</div><blockquote class="notion-quote notion-block-456de830f2054b489d3335a7347d222d"><div>path 开头为 / 的为绝对路径，反之为相对路径。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7119fcf169eb4f5ba9beafb6cfce0d1f" data-id="7119fcf169eb4f5ba9beafb6cfce0d1f"><span><div id="7119fcf169eb4f5ba9beafb6cfce0d1f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7119fcf169eb4f5ba9beafb6cfce0d1f" title="5.2 在父组件中展示"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>5.2 在父组件中展示</b></span></span></h4><div class="notion-text notion-block-ce19f64820c544f184e53ad9f12f2cdd">在父组件中使用<code class="notion-inline-code">Outlet</code><b>来显示匹配到的子组件</b></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-9726e6d7d7774ce7bb15b477653d597b" data-id="9726e6d7d7774ce7bb15b477653d597b"><span><div id="9726e6d7d7774ce7bb15b477653d597b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#9726e6d7d7774ce7bb15b477653d597b" title="5.3 在组件中定义"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>5.3 在组件中定义</b></span></span></h4><div class="notion-text notion-block-b85fd801c1ff465a8b37be07e06c96b6">可以在任何组件中使用 <code class="notion-inline-code">Routes</code> 组件，且组件内的Routes中，路径默认带上当前组件的路径作为前缀。</div><div class="notion-text notion-block-48c3185a1f1a44beadf584a877fb1639">注意：此时定义父组件的路由时，要在后面加上 <code class="notion-inline-code">/*</code> ，否则父组件将无法渲染。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-290548b4e54b43da8c031d33892a4cda" data-id="290548b4e54b43da8c031d33892a4cda"><span><div id="290548b4e54b43da8c031d33892a4cda" class="notion-header-anchor"></div><a class="notion-hash-link" href="#290548b4e54b43da8c031d33892a4cda" title="六、默认路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>六、默认路由</b></span></span></h4><div class="notion-text notion-block-483f2f2e228347e5abc703b8e99a176d"><b>定义：</b> 在嵌套路由中，如果 URL 仅匹配了父级 URL，则<code class="notion-inline-code">Outlet</code>中会显示带有<code class="notion-inline-code">index</code>属性的子路由。可以使用在路由的任何层级</div><ul class="notion-list notion-list-disc notion-block-6e72f889f5f84d03af0b6dbb634c95a5"><li>当 url 为<code class="notion-inline-code">/foo</code>时：Foo 中的 Outlet 会显示 Default 组件</li></ul><ul class="notion-list notion-list-disc notion-block-67976bd3f48c47a38346e6d664148b73"><li>当 url 为<code class="notion-inline-code">/foo/bar</code>时：Foo 中的 Outlet 会显示为 Bar 组件</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1696018f317443fe899a0197db276ad1" data-id="1696018f317443fe899a0197db276ad1"><span><div id="1696018f317443fe899a0197db276ad1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1696018f317443fe899a0197db276ad1" title="七、全匹配路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>七、全匹配路由</b></span></span></h4><div class="notion-text notion-block-e59d12891d764811ba0744f2308656e8"><b>定义：</b> <code class="notion-inline-code">path</code>属性取值为<code class="notion-inline-code">*</code>时，可以匹配任何（非空）路径，该匹配拥有<b>最低的优先级</b>。可以用于设置 404 页面。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-3e7927e8cc05491cab179cd6e0775bde" data-id="3e7927e8cc05491cab179cd6e0775bde"><span><div id="3e7927e8cc05491cab179cd6e0775bde" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3e7927e8cc05491cab179cd6e0775bde" title="八、多组路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>八、多组路由</b></span></span></h4><div class="notion-text notion-block-c0e5e243aaca48af8defbdab2fe054a4">通常，一个应用中只有一个<code class="notion-inline-code">Routes</code>组件。</div><div class="notion-text notion-block-4788beb8732b4df68c85bacd16537398">但根据实际需要也可以定义多个路由出口（如：侧边栏和主页面都要随 URL 而变化）</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ac6b4dcd6fcc4d2c96cab30530deeb81" data-id="ac6b4dcd6fcc4d2c96cab30530deeb81"><span><div id="ac6b4dcd6fcc4d2c96cab30530deeb81" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ac6b4dcd6fcc4d2c96cab30530deeb81" title="九、路由重定向"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>九、路由重定向</b></span></span></h4><div class="notion-text notion-block-7908210e30bb4ac6b581b5f2d34588da">当在某个路径<code class="notion-inline-code">/a</code>下，要重定向到路径<code class="notion-inline-code">/b</code>时，可以通过<code class="notion-inline-code">Navigate</code>组件进行重定向到其他路径</div><blockquote class="notion-quote notion-block-3dc42f4775524ee8b8e998cc915935a0"><div>等价于以前版本中的Redirect组件</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2f978c49bfe54e17ad1307bda7f3b61a" data-id="2f978c49bfe54e17ad1307bda7f3b61a"><span><div id="2f978c49bfe54e17ad1307bda7f3b61a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2f978c49bfe54e17ad1307bda7f3b61a" title="十、布局路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>十、布局路由</b></span></span></h4><div class="notion-text notion-block-d449042fad17432baa49bb9470200550">当多个路由有共同的父级组件时，可以将父组件提取为一个没有 <code class="notion-inline-code">path</code> 和 <code class="notion-inline-code">index</code> 属性的Route组件（Layout Route）</div><div class="notion-text notion-block-0b74104242c247188a609b7e4af3416b">这种写法等价于：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-bedf2a556ed441dcb1ef5b94194132a7" data-id="bedf2a556ed441dcb1ef5b94194132a7"><span><div id="bedf2a556ed441dcb1ef5b94194132a7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#bedf2a556ed441dcb1ef5b94194132a7" title="十一、订阅和操作 history stack的原理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>十一、订阅和操作 history stack的原理</b></span></span></h4><div class="notion-text notion-block-c5274b0d2422456c98569cd425c4d433">浏览器会记录导航堆栈，以实现浏览器中的前进后退功能。在传统的前端项目中，URL的改变意味着向服务器重新请求数据。</div><div class="notion-text notion-block-6a3b1909359c4a5195c71827ef62b260">在现在的客户端路由（ client side routing ）中，可以做到编程控制URL改变后的反应。如在点击a标签的回调函数中使用 <code class="notion-inline-code">event.preventDefault()</code> 阻止默认事件，此时URL的改变不会带来任何UI上的更新。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7cd0635c81ad445b94b8f247295dacc1" data-id="7cd0635c81ad445b94b8f247295dacc1"><span><div id="7cd0635c81ad445b94b8f247295dacc1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7cd0635c81ad445b94b8f247295dacc1" title="11.1 History对象"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>11.1 History对象</b></span></span></h4><div class="notion-text notion-block-020a44da62884e3d8e46ce3aa81df6c4">浏览器没有直接提供监听URL改变（push、pop、replace）的接口，因此 <code class="notion-inline-code">react-router</code> 对原生的 <code class="notion-inline-code">history</code> 对线进行了包装，提供了监听URL改变的API。</div><div class="notion-text notion-block-274ec73ac7d340fe9d9b2975a859490f">使用 <code class="notion-inline-code">react-router</code> 时不需操作History对象（<code class="notion-inline-code">Routes</code> 组件会进行操作）</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-37994065af434a028a7809ed4f7b4992" data-id="37994065af434a028a7809ed4f7b4992"><span><div id="37994065af434a028a7809ed4f7b4992" class="notion-header-anchor"></div><a class="notion-hash-link" href="#37994065af434a028a7809ed4f7b4992" title="11.2 Location对象"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>11.2 Location对象</b></span></span></h4><div class="notion-text notion-block-4002daa8be5546f5bef533555c66f979"><code class="notion-inline-code">react-router</code> 对 <code class="notion-inline-code">window.location</code> 进行包装后，提供了一个形式简洁的Location对象，形如：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1732a04d9859457a9794687a1a2df8a3" data-id="1732a04d9859457a9794687a1a2df8a3"><span><div id="1732a04d9859457a9794687a1a2df8a3" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1732a04d9859457a9794687a1a2df8a3" title="state"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>state</b></span></span></h4><div class="notion-text notion-block-d17288a87ccf4bfcaa7087bc03802b24">不显示在页面上，不会引起刷新，只由开发人员操作。</div><div class="notion-text notion-block-fd1164bfa3cc4e989089daa1c263693e">可用于记录用户的跳转详情（从哪跳到当前页面）或在跳转时携带信息。</div><div class="notion-text notion-block-79ca34d4dc044a6d9436b5feebd8bc92">可以用在 <code class="notion-inline-code">Link</code> 组件或 <code class="notion-inline-code">navigate</code> 方法中</div><div class="notion-text notion-block-72177045bdc14dbd8e807d6bb68a2825">在目标的组件中，可以用 <code class="notion-inline-code">useLocation</code> 方法获取该对象</div><blockquote class="notion-quote notion-block-756716deded74d6686a2b4f17a33e8a9"><div>state中的信息会进行序列化，因此如日期对象等信息会变为string</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-d6315337f96a4243b138f667322d85b0" data-id="d6315337f96a4243b138f667322d85b0"><span><div id="d6315337f96a4243b138f667322d85b0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d6315337f96a4243b138f667322d85b0" title="key"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>key</b></span></span></h4><div class="notion-text notion-block-4b2e4d50f9aa40ab91b099ba7645a56d">每个Location对象拥有一个唯一的key，可以据此来实现基于Location的滚动管理，或是数据缓存。</div><div class="notion-text notion-block-6090eb84892a427ba6da96d55204d697">如：将 <code class="notion-inline-code">location.key</code> 和 URL 作为键，每次请求数据前，先查找缓存是否存在来判断是否实际发送请求，来实现客户端数据缓存。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-4778240986fa4dcfb4f5759af28fb683" data-id="4778240986fa4dcfb4f5759af28fb683"><span><div id="4778240986fa4dcfb4f5759af28fb683" class="notion-header-anchor"></div><a class="notion-hash-link" href="#4778240986fa4dcfb4f5759af28fb683" title="十二、 各类Router组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>十二、 各类Router组件</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-5d6d7c16d68d47b79b9cd550b3ebb2a9" data-id="5d6d7c16d68d47b79b9cd550b3ebb2a9"><span><div id="5d6d7c16d68d47b79b9cd550b3ebb2a9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5d6d7c16d68d47b79b9cd550b3ebb2a9" title="12.1 HashRouter和BrowserRouter的区别"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.1 HashRouter和BrowserRouter的区别</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-0f604525b72d4ac2b12baad71745e4c7"><li><code class="notion-inline-code">HashRouter</code> 只会修改URL中的哈希值部分；而 <code class="notion-inline-code">BrowserRouter</code> 修改的是URL本身</li></ul><ul class="notion-list notion-list-disc notion-block-cf8fb22609d14b62b18ca1591f297388"><li><code class="notion-inline-code">HashRouter</code> 是<b>纯前端</b>路由，可以通过输入URL直接访问；使用时 <code class="notion-inline-code">BrowserRouter</code> 直接输入URL会显示404，除非配置Nginx将请求指向对应的HTML文件。初次进入 <code class="notion-inline-code">/</code> 路径时或点击 <code class="notion-inline-code">Link</code> 组件跳转时不会发送请求</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-50c233440b56405fbc31b01163096fdd" data-id="50c233440b56405fbc31b01163096fdd"><span><div id="50c233440b56405fbc31b01163096fdd" class="notion-header-anchor"></div><a class="notion-hash-link" href="#50c233440b56405fbc31b01163096fdd" title="12.2 unstable_HistoryRouter"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.2 unstable_HistoryRouter</b></span></span></h4><div class="notion-text notion-block-da87a808c79f4803bacf27d6e39444e1">使用 <code class="notion-inline-code">unstable_HistoryRouter</code> 需要传入一个 <code class="notion-inline-code">history</code> 库的实例，这将允许在非react作用于下操作history对象。</div><blockquote class="notion-quote notion-block-a85c5c59859645a287d2041f73210d9b"><div>由于项目使用的history和react-router中使用的history版本可能不一样，该API目前标为unstable状态</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-87f10f35e35c4727a7e40c032dd534f6" data-id="87f10f35e35c4727a7e40c032dd534f6"><span><div id="87f10f35e35c4727a7e40c032dd534f6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#87f10f35e35c4727a7e40c032dd534f6" title="12.3 MemoryRouter"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.3 MemoryRouter</b></span></span></h4><div class="notion-text notion-block-5d2ebd02e52f402fa13a6716007d8550"><code class="notion-inline-code">HashRouter</code> 和 <code class="notion-inline-code">BrowserRouter</code> 都是依据外部对象（history）进行导航，而 <code class="notion-inline-code">MemoryRouter</code> 则是自己存储和管理状态堆栈，多用于测试场景。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-159257c9ecb748259a1556d4dfeae18c" data-id="159257c9ecb748259a1556d4dfeae18c"><span><div id="159257c9ecb748259a1556d4dfeae18c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#159257c9ecb748259a1556d4dfeae18c" title="12.4 NativeRouter"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.4 NativeRouter</b></span></span></h4><div class="notion-text notion-block-7cb38baf12234b73885cc89b1b21fc45">推荐的用于 React Native的Router组件</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-3c31b0e7140246df843601aa17cf8410" data-id="3c31b0e7140246df843601aa17cf8410"><span><div id="3c31b0e7140246df843601aa17cf8410" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3c31b0e7140246df843601aa17cf8410" title="12.5 StaticRouter"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.5 StaticRouter</b></span></span></h4><div class="notion-text notion-block-526c18a23cd74349a45373fce372f088">在nodejs端使用，渲染react应用。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-01dce95f966b472c9ae69f36182910ae" data-id="01dce95f966b472c9ae69f36182910ae"><span><div id="01dce95f966b472c9ae69f36182910ae" class="notion-header-anchor"></div><a class="notion-hash-link" href="#01dce95f966b472c9ae69f36182910ae" title="十三、使用JS对象定义路由（路由表）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>十三、使用JS对象定义路由（路由表）</b></span></span></h4><div class="notion-text notion-block-233a7ca33f5941b28d91ed96f65df837">使用 <code class="notion-inline-code">useRoutes</code> hook，可以使用一个JS对象而不是Routes组件与Route组件来定义路由。其功能类似于<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://link.juejin.cn/?target=https%3A%2F%2Flink.zhihu.com%2F%3Ftarget%3Dhttps%3A%2F%2Fwww.npmjs.com%2Fpackage%2Freact-router-config">react-router-config(opens new window)</a></div><div class="notion-text notion-block-8fdc67aced6349429732b851ce920dad"><code class="notion-inline-code">useRoutes</code> 的返回是 React Element，或是 null。</div><div class="notion-text notion-block-c1a896789ea74c2480afd0072fb56101">此功能用来管理路由表，相比v5，可能需要借助一些第三方库来实现路由config管理，现在v6版本自带</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-eca031fc5c834ba1bf7ae4653e1b8957" data-id="eca031fc5c834ba1bf7ae4653e1b8957"><span><div id="eca031fc5c834ba1bf7ae4653e1b8957" class="notion-header-anchor"></div><a class="notion-hash-link" href="#eca031fc5c834ba1bf7ae4653e1b8957" title="(一) 创建路由表"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>(一) 创建路由表</b></span></span></h4><div class="notion-text notion-block-9087331d30774103b4e846cb6aae3310">对于传入的配置对象， 其类型定义如下：</div><div class="notion-text notion-block-bc504f20609945cb9d25c8aed4b31a82">提示</div><div class="notion-text notion-block-fcd73697ce2f4c7cb09494970158ccf6">也可以单独创建 routes 文件夹管理路由表，然后在组件内使用 useRoutes</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-3b8bb596f3394703a6acc250419e6828" data-id="3b8bb596f3394703a6acc250419e6828"><span><div id="3b8bb596f3394703a6acc250419e6828" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3b8bb596f3394703a6acc250419e6828" title="(二) 组件结构内使用函数返回值作为占位符"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>(二) 组件结构内使用函数返回值作为占位符</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-0c678048872146c08c709884becc7474" data-id="0c678048872146c08c709884becc7474"><span><div id="0c678048872146c08c709884becc7474" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0c678048872146c08c709884becc7474" title="(三) 嵌套路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>(三) 嵌套路由</b></span></span></h4><blockquote class="notion-quote notion-block-a0d0a8bdd82444f5b513b88732957357"><div>在一级路由下面创建二级子路由</div></blockquote><ol start="1" class="notion-list notion-list-numbered notion-block-3bf2d50ac36d4c559b1e33f117d0c56d"><li>引入路由路由占位符OutLet到组件中</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-52a61112fd404fe294b20989688b02ea"><li>引入NavLink到组件中改变路径，子路由路径可以不需要加<code class="notion-inline-code">/</code></li></ol><div class="notion-text notion-block-644057d68a8d49eaac2f27c7a998c7d4">注意</div><div class="notion-text notion-block-bc678283678c46398c658ea5680fbd94"><b>不要忘记使用Outlet作为占位符</b></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-c13581df46e24d51a7ce1e6573310d09" data-id="c13581df46e24d51a7ce1e6573310d09"><span><div id="c13581df46e24d51a7ce1e6573310d09" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c13581df46e24d51a7ce1e6573310d09" title="(四) 路由懒加载"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>(四) 路由懒加载</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-28be0e6b796241d5ba4938873fb28887" data-id="28be0e6b796241d5ba4938873fb28887"><span><div id="28be0e6b796241d5ba4938873fb28887" class="notion-header-anchor"></div><a class="notion-hash-link" href="#28be0e6b796241d5ba4938873fb28887" title="十四、其他hooks函数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>十四、其他hooks函数</b></span></span></h4><div class="notion-text notion-block-1eeb75c930874234b8bcb35c125dd603">直接在组件中调用即可</div><hr class="notion-hr notion-block-5e672b422e5043eab553bcd60b24aff1"/><blockquote class="notion-quote notion-block-a9cc868ad73944f99971526e2907f08d"><div>useRouterContext</div></blockquote><div class="notion-text notion-block-b6b64f42376f4bc9bf7f80f9c443c911">作用：判断组件是否被路由包裹</div><hr class="notion-hr notion-block-d341eb578dd84277a61d2e051d463553"/><blockquote class="notion-quote notion-block-f1517e7f8eae4c35b3fadb2839cfff02"><div>useNavigationType</div></blockquote><div class="notion-text notion-block-f652400b8ae14ae3833c2ddb116ef6cb">作用：判断路由跳转方式</div><div class="notion-text notion-block-58abb56af8874a76b8ca08b2949c4a57">返回值：<code class="notion-inline-code">push</code> <code class="notion-inline-code">pop</code> <code class="notion-inline-code">replace</code></div><div class="notion-text notion-block-2dc86747feaa4493bf79062aa035b747">pop是在浏览器中直接打开了这个路由的组件</div><hr class="notion-hr notion-block-4620c4609baa4c61a280a3d7f250b02e"/><blockquote class="notion-quote notion-block-c7ca7ee7454a4d3bbd5015e66b7fc88a"><div>useOutlet</div></blockquote><div class="notion-text notion-block-81c08b63b8264180baa0f7799de73013">作用：查看组件下级路由信息</div><div class="notion-text notion-block-9e20717b421943f89628cad007c9fd86">组件若未被挂载则返回null，若以被挂载，则返回该子组件信息</div><hr class="notion-hr notion-block-736723b8b06c4fa7ade39a77eca37e8e"/><blockquote class="notion-quote notion-block-8c294b7636db468b99410580b7aafed3"><div>useResolvePath</div></blockquote><div class="notion-text notion-block-9ae86154b127424b823fa3459d23ef14">作用：解析路径</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-d809a55ce4ed48c6a51403d573d6eea1" data-id="d809a55ce4ed48c6a51403d573d6eea1"><span><div id="d809a55ce4ed48c6a51403d573d6eea1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d809a55ce4ed48c6a51403d573d6eea1" title="动态路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>动态路由</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-b85538f5e31c4206a44234633ffde1d2" data-id="b85538f5e31c4206a44234633ffde1d2"><span><div id="b85538f5e31c4206a44234633ffde1d2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b85538f5e31c4206a44234633ffde1d2" title="router/index.ts 默认路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>router/index.ts 默认路由</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-57ddbdecc41545a78909f4d3fb85f14c" data-id="57ddbdecc41545a78909f4d3fb85f14c"><span><div id="57ddbdecc41545a78909f4d3fb85f14c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#57ddbdecc41545a78909f4d3fb85f14c" title="redux login/action.ts"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>redux login/action.ts</b></span></span></h4><div class="notion-text notion-block-a2b9d94e8e51441eb8594201f9283b24"><b>注意带 //import! 的标识</b> 每次导航列表更新时，再触发路由更新action handelFilterRouter 就是根据导航菜单列表 和权限列表 得出路由表的</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7493b09482e344818ef674ef3c1b2f2f" data-id="7493b09482e344818ef674ef3c1b2f2f"><span><div id="7493b09482e344818ef674ef3c1b2f2f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7493b09482e344818ef674ef3c1b2f2f" title="utils 工具函数处理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>utils 工具函数处理</b></span></span></h4><div class="notion-text notion-block-6144acc27ce34a2f8708d156b5cabcf7">说一说我这里为什么要映射element 成对应组件这部操作，原因是我使用了redux-persist（redux持久化。</div><div class="notion-text notion-block-3f39265feb094c66a5cfa9c870439e24">若是直接转换后存入本地再取出来渲染是会有问题的，所以需要先将element保存成映射路径，然后渲染前再进行一次路径映射出对应组件。</div><div class="notion-text notion-block-3d365eb21e7b40918a7824f5f3cdab16"><b>每个后台的数据返回格式都不一样，需要自己去转换，我这里的转换仅供参考。</b> <b>ps:defaulyRoutes和默认router/index.ts导出是一样的，可以做个小优化，复用起来。</b></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-773697d2359d4d80830217a24b796ca7" data-id="773697d2359d4d80830217a24b796ca7"><span><div id="773697d2359d4d80830217a24b796ca7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#773697d2359d4d80830217a24b796ca7" title="App.tsx"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>App.tsx</b></span></span></h4><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-1eb37bd7b7144192a3ce84793db43d90" data-id="1eb37bd7b7144192a3ce84793db43d90"><span><div id="1eb37bd7b7144192a3ce84793db43d90" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1eb37bd7b7144192a3ce84793db43d90" title="路由传参"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由传参</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-b3a6b1baeeb64c7d8fe27117ca2277f5" data-id="b3a6b1baeeb64c7d8fe27117ca2277f5"><span><div id="b3a6b1baeeb64c7d8fe27117ca2277f5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b3a6b1baeeb64c7d8fe27117ca2277f5" title="1. params传参"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1. params传参</b></span></span></h4><div class="notion-text notion-block-fb25e9f73baf4baab746e97f4fea3a38">优点：刷新页面，参数不丢失</div><div class="notion-text notion-block-8cf5394bd06d4f99ab06be478ee7a764">缺点：1.只能传字符串，传值过多url会变得很长 2. 参数必须在路由上配置</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-0edd7495d2f7447a88e062c515afaa5e" data-id="0edd7495d2f7447a88e062c515afaa5e"><span><div id="0edd7495d2f7447a88e062c515afaa5e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0edd7495d2f7447a88e062c515afaa5e" title="路由配置"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由配置</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-c0ce3f3b918c488fbefd49d7ee974239" data-id="c0ce3f3b918c488fbefd49d7ee974239"><span><div id="c0ce3f3b918c488fbefd49d7ee974239" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c0ce3f3b918c488fbefd49d7ee974239" title="路由跳转与获取路由参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由跳转与获取路由参数</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ac561b629dbe4613a8819f85e96a93c9" data-id="ac561b629dbe4613a8819f85e96a93c9"><span><div id="ac561b629dbe4613a8819f85e96a93c9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ac561b629dbe4613a8819f85e96a93c9" title="2. search传参"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2. search传参</b></span></span></h4><div class="notion-text notion-block-2a0f7d99a3de45fc851b6c93741c3583">优点：刷新页面，参数不丢失</div><div class="notion-text notion-block-43dc06a6f8c947fbbace23241c8ab241">缺点：只能传字符串，传值过多url会变得很长，获取参数需要自定义hooks</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-d4d183d194614e50a2649e0b515caaeb" data-id="d4d183d194614e50a2649e0b515caaeb"><span><div id="d4d183d194614e50a2649e0b515caaeb" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d4d183d194614e50a2649e0b515caaeb" title="路由配置"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由配置</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-3a341d3ba1744ebb8c178a3b58206840" data-id="3a341d3ba1744ebb8c178a3b58206840"><span><div id="3a341d3ba1744ebb8c178a3b58206840" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3a341d3ba1744ebb8c178a3b58206840" title="路由跳转与获取路由参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由跳转与获取路由参数</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-a2c842307f5848d9aa53a379f1d0eea2" data-id="a2c842307f5848d9aa53a379f1d0eea2"><span><div id="a2c842307f5848d9aa53a379f1d0eea2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a2c842307f5848d9aa53a379f1d0eea2" title="3. state传参🙌"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>3. state传参🙌</b></span></span></h4><div class="notion-text notion-block-b57f08d0d5c9418394effdd0a9d7a102">优点：可以传对象</div><div class="notion-text notion-block-49b2fb8364184c77b6518fa03135d976">缺点： <code class="notion-inline-code">&lt;HashRouter&gt;</code>刷新页面，参数丢失</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-0ff623e717d64f5989667c00e4072d5a" data-id="0ff623e717d64f5989667c00e4072d5a"><span><div id="0ff623e717d64f5989667c00e4072d5a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0ff623e717d64f5989667c00e4072d5a" title="路由配置"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由配置</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-bfc3dd3046464afca75a855ea896283c" data-id="bfc3dd3046464afca75a855ea896283c"><span><div id="bfc3dd3046464afca75a855ea896283c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#bfc3dd3046464afca75a855ea896283c" title="路由跳转与获取路由参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由跳转与获取路由参数</b></span></span></h4><div class="notion-text notion-block-1b6e3e5d78724273ac1fde461d240785">笔记</div><div class="notion-text notion-block-6b1728950018497f934657e828a3e87b"><code class="notion-inline-code">&lt;HashRouter&gt;</code> 不支持 <code class="notion-inline-code">location.key</code> 与 <code class="notion-inline-code">location.state</code>，<code class="notion-inline-code">&lt;HashRouter&gt;</code>通过<code class="notion-inline-code">state</code>传递参数，刷新页面后参数丢失，官方建议使用<code class="notion-inline-code">&lt;BrowserRouter&gt;</code>，<code class="notion-inline-code">&lt;BrowserRouter&gt;</code>页面刷新参数也不会丢失。</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-86f4590a150f41acbb9dc774aaa9db0f" data-id="86f4590a150f41acbb9dc774aaa9db0f"><span><div id="86f4590a150f41acbb9dc774aaa9db0f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#86f4590a150f41acbb9dc774aaa9db0f" title="Router"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>Router</b></span></span></h2><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-460a98dd528d43e380a2f01f63873367" data-id="460a98dd528d43e380a2f01f63873367"><span><div id="460a98dd528d43e380a2f01f63873367" class="notion-header-anchor"></div><a class="notion-hash-link" href="#460a98dd528d43e380a2f01f63873367" title="详细使用示例"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>详细使用示例</b></span></span></h3><div class="notion-text notion-block-bffdde23c73348a0ac1c7ff02864ac80">注意：这里使用的时最新的 v6 版本，已完全弃用了原先的 react-router 库，较 v5 版本有很大的改动。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2c49742c6bc544cbb39b5fba09d258da" data-id="2c49742c6bc544cbb39b5fba09d258da"><span><div id="2c49742c6bc544cbb39b5fba09d258da" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2c49742c6bc544cbb39b5fba09d258da" title="一、基本使用"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>一、基本使用</b></span></span></h4><ol start="1" class="notion-list notion-list-numbered notion-block-647c03399b8e4a2fa10d06d9b870d501"><li>首先安装依赖</li></ol><ol start="1" class="notion-list notion-list-numbered notion-block-ab7f3a356c0a43e5990b26ff6876c9f1"><li>引入实现路由所需的组件，以及页面组件</li></ol><ul class="notion-list notion-list-disc notion-block-660f23e9a4014b089d303089c7c608c5"><li><code class="notion-inline-code">path</code>：路径</li></ul><ul class="notion-list notion-list-disc notion-block-360f3e77158141038c71d1ee6e656b12"><li><code class="notion-inline-code">element</code>：要渲染的组件</li></ul><blockquote class="notion-quote notion-block-b349549c2c114127bacd45f4aabfb435"><div>注意：BrowserRouter组件最好放在最顶层所有组件之外，这样能确保内部组件使用 Link 做路由跳转时不出错</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-873c0dadbda440fcbc1f7ac54fc8fbe9" data-id="873c0dadbda440fcbc1f7ac54fc8fbe9"><span><div id="873c0dadbda440fcbc1f7ac54fc8fbe9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#873c0dadbda440fcbc1f7ac54fc8fbe9" title="二、路由跳转"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>二、路由跳转</b></span></span></h4><div class="notion-text notion-block-221af0e996d84a74ac66289271737c35">在跳转路由时，如果路径是<code class="notion-inline-code">/</code>开头的则是绝对路由，否则为<b>相对路由</b>，即<b>相对于当前 URL</b>进行改变</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-83c92663555e40ad99e90ce125434ab2" data-id="83c92663555e40ad99e90ce125434ab2"><span><div id="83c92663555e40ad99e90ce125434ab2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#83c92663555e40ad99e90ce125434ab2" title="2.1 Link 组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.1 Link 组件</b></span></span></h4><div class="notion-text notion-block-7fc0d7a3bca84ac79ead713e55b78ce2"><code class="notion-inline-code">Link组件</code>只能在<code class="notion-inline-code">Router</code>内部使用，因此使用到<code class="notion-inline-code">Link组件</code>的组件一定要放在顶层的 Router 之内</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-a47368cf81cf4782b1477ba15660ee6b" data-id="a47368cf81cf4782b1477ba15660ee6b"><span><div id="a47368cf81cf4782b1477ba15660ee6b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a47368cf81cf4782b1477ba15660ee6b" title="2.2 NavLink 组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.2 NavLink 组件</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-3aea62c471674df4bc6c86bdb346fdb3"><li><code class="notion-inline-code">NavLink组件</code>和<code class="notion-inline-code">Link组件</code>的功能是一致的，区别在于可以判断其<code class="notion-inline-code">to属性</code>是否是当前匹配到的路由</li></ul><ul class="notion-list notion-list-disc notion-block-a8c8332308a04d89bfd91b502e1ab174"><li><code class="notion-inline-code">NavLink组件</code>的<code class="notion-inline-code">style</code>或<code class="notion-inline-code">className</code>可以接收一个函数，函数接收一个含有<code class="notion-inline-code">isActive</code>字段的对象为参数，可根据该参数调整样式</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-6e6b1b7964f045a9b2354376e1088ba0" data-id="6e6b1b7964f045a9b2354376e1088ba0"><span><div id="6e6b1b7964f045a9b2354376e1088ba0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#6e6b1b7964f045a9b2354376e1088ba0" title="2.3 编程式跳转"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2.3 编程式跳转</b></span></span></h4><div class="notion-text notion-block-d9f4a9c0eae24a86a95b1550a8dd6a77">使用<code class="notion-inline-code">useNavigate</code>钩子函数生成<code class="notion-inline-code">navigate函数</code>，可以通过 JS 代码完成路由跳转</div><blockquote class="notion-quote notion-block-dc5ce8b5b5854357bcb8556617530cbb"><div>useNavigate`取代了原先版本中的`useHistory</div></blockquote><ul class="notion-list notion-list-disc notion-block-e8ae48cd13b141598e4db4f5258c1880"><li>可以直接传入要跳转的目标路由（可以使用相对路径，语法和 JS 相同）</li></ul><ul class="notion-list notion-list-disc notion-block-e6c22c53fad847b9a2188168952afac4"><li>传入<code class="notion-inline-code">1</code>表示后退</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7382a8825ac24880ac3d9ffc90e22d93" data-id="7382a8825ac24880ac3d9ffc90e22d93"><span><div id="7382a8825ac24880ac3d9ffc90e22d93" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7382a8825ac24880ac3d9ffc90e22d93" title="四、动态路由参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>四、动态路由参数</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-55fd980552cd49d88e5d007423f7fa99" data-id="55fd980552cd49d88e5d007423f7fa99"><span><div id="55fd980552cd49d88e5d007423f7fa99" class="notion-header-anchor"></div><a class="notion-hash-link" href="#55fd980552cd49d88e5d007423f7fa99" title="4.1 路径参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.1 路径参数</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-b150969370604829baa61dc5246b64fc"><li>在<code class="notion-inline-code">Route组件</code>中的<code class="notion-inline-code">path属性</code>中定义路径参数</li></ul><ul class="notion-list notion-list-disc notion-block-4211c5bb03704d5c898763dd794a83ae"><li>在组件内通过<code class="notion-inline-code">useParams</code> hook 访问路径参数</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-f459c285ca3b4833b9b26815fb2cd3ba" data-id="f459c285ca3b4833b9b26815fb2cd3ba"><span><div id="f459c285ca3b4833b9b26815fb2cd3ba" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f459c285ca3b4833b9b26815fb2cd3ba" title="路径匹配规则"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路径匹配规则</b></span></span></h4><div class="notion-text notion-block-e0fefcff222542febb45c7337d604872">当URL同时匹配到含有路径参数的路径和无参数路径时，有限匹配没有参数的”具体的“（specific）路径。</div><div class="notion-text notion-block-70797f66cf82411893aac02a0299c070">如上的两个路径，将会匹配 <code class="notion-inline-code">teams/new</code> 。</div><div class="notion-text notion-block-0de74147eac04d1083eb491f96bc06c3">路径的正则匹配已被移除。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-43fe003858244ae08f96ed7946d663d1" data-id="43fe003858244ae08f96ed7946d663d1"><span><div id="43fe003858244ae08f96ed7946d663d1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#43fe003858244ae08f96ed7946d663d1" title="兼容类组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>兼容类组件</b></span></span></h4><div class="notion-text notion-block-2c25d887402d42fdb52fc5f4dc778d77">在以前版本中，组件的<code class="notion-inline-code">props</code>会包含一个<code class="notion-inline-code">match对象</code>，在其中可以取到路径参数。</div><div class="notion-text notion-block-be9b0fceff1c4b6d9fe29e2a2f2b9863">但在最新的 6.x 版本中，无法从 props 获取参数。</div><div class="notion-text notion-block-d5597b04547e430fb4b3bcae72fb430a">并且，针对类组件的 <code class="notion-inline-code">withRouter</code> 高阶组件已被移除。因此对于类组件来说，使用参数有两种兼容方法：</div><ol start="1" class="notion-list notion-list-numbered notion-block-c249b8dbf613402eb12d3bde49fe049e"><li>将类组件改写为函数组件</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-e9041c423a5944d288f74e635bbba2c5"><li>自己写一个 HOC 来包裹类组件，用 <code class="notion-inline-code">useParams</code> 获取参数后通过 props 传入原本的类组件</li></ol><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-35db060e60a246d2b5c96d33a573b824" data-id="35db060e60a246d2b5c96d33a573b824"><span><div id="35db060e60a246d2b5c96d33a573b824" class="notion-header-anchor"></div><a class="notion-hash-link" href="#35db060e60a246d2b5c96d33a573b824" title="4.2 search 参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>4.2 search 参数</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-962b35b9bc504dc8a49f0ecf12ad8ab2"><li>查询参数不需要在路由中定义</li></ul><ul class="notion-list notion-list-disc notion-block-c32f0d6cabbb4867b6d150059bba7e92"><li>使用 <code class="notion-inline-code">useSearchParams</code> hook 来访问和修改查询参数。其用法和 <code class="notion-inline-code">useState</code> 类似，会返回当前对象和更改它的方法</li></ul><ul class="notion-list notion-list-disc notion-block-d4d602a1ab2c4682959d4b266c12ad9c"><li>使用 <code class="notion-inline-code">setSearchParams</code> 时，<b>必须传入所有的查询参数</b>，否则会覆盖已有参数</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-75f54b67fc224bdea315fc8e5b68d33d" data-id="75f54b67fc224bdea315fc8e5b68d33d"><span><div id="75f54b67fc224bdea315fc8e5b68d33d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#75f54b67fc224bdea315fc8e5b68d33d" title="五、嵌套路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>五、嵌套路由</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1cee98f001aa425783f6a1c521397abe" data-id="1cee98f001aa425783f6a1c521397abe"><span><div id="1cee98f001aa425783f6a1c521397abe" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1cee98f001aa425783f6a1c521397abe" title="5.1 路由定义"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>5.1 路由定义</b></span></span></h4><div class="notion-text notion-block-c5554bca54154e22b17dd969bb5de35b">通过嵌套的书写<code class="notion-inline-code">Route组件</code>实现对嵌套路由的定义。</div><blockquote class="notion-quote notion-block-03b1208d23f24dafafa7498175c8387e"><div>path 开头为 / 的为绝对路径，反之为相对路径。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-8930a9908ce04fe8a4de8c24a5dd8629" data-id="8930a9908ce04fe8a4de8c24a5dd8629"><span><div id="8930a9908ce04fe8a4de8c24a5dd8629" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8930a9908ce04fe8a4de8c24a5dd8629" title="5.2 在父组件中展示"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>5.2 在父组件中展示</b></span></span></h4><div class="notion-text notion-block-a37bd465ef3e42b39e70047d3d7662bf">在父组件中使用<code class="notion-inline-code">Outlet</code><b>来显示匹配到的子组件</b></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-d5c6c2b9928645bbb0cffccbfbab1809" data-id="d5c6c2b9928645bbb0cffccbfbab1809"><span><div id="d5c6c2b9928645bbb0cffccbfbab1809" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d5c6c2b9928645bbb0cffccbfbab1809" title="5.3 在组件中定义"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>5.3 在组件中定义</b></span></span></h4><div class="notion-text notion-block-c6dcd6552aeb46d9a594d066f188e577">可以在任何组件中使用 <code class="notion-inline-code">Routes</code> 组件，且组件内的Routes中，路径默认带上当前组件的路径作为前缀。</div><div class="notion-text notion-block-6f2c7a503290486a9fe5543d494a785f">注意：此时定义父组件的路由时，要在后面加上 <code class="notion-inline-code">/*</code> ，否则父组件将无法渲染。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-4082da27711a46bfab315dd5ccf4f3c6" data-id="4082da27711a46bfab315dd5ccf4f3c6"><span><div id="4082da27711a46bfab315dd5ccf4f3c6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#4082da27711a46bfab315dd5ccf4f3c6" title="六、默认路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>六、默认路由</b></span></span></h4><div class="notion-text notion-block-3cca0de4e46b45539e681b8d6b58a944"><b>定义：</b> 在嵌套路由中，如果 URL 仅匹配了父级 URL，则<code class="notion-inline-code">Outlet</code>中会显示带有<code class="notion-inline-code">index</code>属性的子路由。可以使用在路由的任何层级</div><ul class="notion-list notion-list-disc notion-block-3d9f980c1a2e484e8b53404925cd3e56"><li>当 url 为<code class="notion-inline-code">/foo</code>时：Foo 中的 Outlet 会显示 Default 组件</li></ul><ul class="notion-list notion-list-disc notion-block-041a4ecd2b7e4451b13a3b79a6bdcb60"><li>当 url 为<code class="notion-inline-code">/foo/bar</code>时：Foo 中的 Outlet 会显示为 Bar 组件</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e813a238fa7c419b9f82c7d059b03788" data-id="e813a238fa7c419b9f82c7d059b03788"><span><div id="e813a238fa7c419b9f82c7d059b03788" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e813a238fa7c419b9f82c7d059b03788" title="七、全匹配路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>七、全匹配路由</b></span></span></h4><div class="notion-text notion-block-6b1a66c8a2c54008bd7c9ce2e7c062f0"><b>定义：</b> <code class="notion-inline-code">path</code>属性取值为<code class="notion-inline-code">*</code>时，可以匹配任何（非空）路径，该匹配拥有<b>最低的优先级</b>。可以用于设置 404 页面。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-a08dd48f79554d8cbd5e8171e9036d55" data-id="a08dd48f79554d8cbd5e8171e9036d55"><span><div id="a08dd48f79554d8cbd5e8171e9036d55" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a08dd48f79554d8cbd5e8171e9036d55" title="八、多组路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>八、多组路由</b></span></span></h4><div class="notion-text notion-block-1e6977b26ef8455d95849b430a31fbd2">通常，一个应用中只有一个<code class="notion-inline-code">Routes</code>组件。</div><div class="notion-text notion-block-fc6700a081294f429689b41f7fd4f4fb">但根据实际需要也可以定义多个路由出口（如：侧边栏和主页面都要随 URL 而变化）</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-c1b39be94a8e4152962c27adf1b08ae7" data-id="c1b39be94a8e4152962c27adf1b08ae7"><span><div id="c1b39be94a8e4152962c27adf1b08ae7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c1b39be94a8e4152962c27adf1b08ae7" title="九、路由重定向"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>九、路由重定向</b></span></span></h4><div class="notion-text notion-block-bca71a43c2cd4bf7b63ec14162ddb638">当在某个路径<code class="notion-inline-code">/a</code>下，要重定向到路径<code class="notion-inline-code">/b</code>时，可以通过<code class="notion-inline-code">Navigate</code>组件进行重定向到其他路径</div><blockquote class="notion-quote notion-block-b7377171e49541fc9bb5db606fef5504"><div>等价于以前版本中的Redirect组件</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-30940d0ba45048608ac12245b74b9b4d" data-id="30940d0ba45048608ac12245b74b9b4d"><span><div id="30940d0ba45048608ac12245b74b9b4d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#30940d0ba45048608ac12245b74b9b4d" title="十、布局路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>十、布局路由</b></span></span></h4><div class="notion-text notion-block-9df5f8dab07a4ccdbcf9c9c7cfbffbc9">当多个路由有共同的父级组件时，可以将父组件提取为一个没有 <code class="notion-inline-code">path</code> 和 <code class="notion-inline-code">index</code> 属性的Route组件（Layout Route）</div><div class="notion-text notion-block-bde4eeb1916b47978ebecc81b72c0fac">这种写法等价于：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-308f145b232b4b50bb27a85f8d94a077" data-id="308f145b232b4b50bb27a85f8d94a077"><span><div id="308f145b232b4b50bb27a85f8d94a077" class="notion-header-anchor"></div><a class="notion-hash-link" href="#308f145b232b4b50bb27a85f8d94a077" title="十一、订阅和操作 history stack的原理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>十一、订阅和操作 history stack的原理</b></span></span></h4><div class="notion-text notion-block-81bd5ce7106940c89defa7febe1e60cb">浏览器会记录导航堆栈，以实现浏览器中的前进后退功能。在传统的前端项目中，URL的改变意味着向服务器重新请求数据。</div><div class="notion-text notion-block-530a2aa4d61d4c559d0173915cfaa2f0">在现在的客户端路由（ client side routing ）中，可以做到编程控制URL改变后的反应。如在点击a标签的回调函数中使用 <code class="notion-inline-code">event.preventDefault()</code> 阻止默认事件，此时URL的改变不会带来任何UI上的更新。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-92c60df3096c4e15a0baf1f87be3d2fa" data-id="92c60df3096c4e15a0baf1f87be3d2fa"><span><div id="92c60df3096c4e15a0baf1f87be3d2fa" class="notion-header-anchor"></div><a class="notion-hash-link" href="#92c60df3096c4e15a0baf1f87be3d2fa" title="11.1 History对象"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>11.1 History对象</b></span></span></h4><div class="notion-text notion-block-201e8e29244f42f08bde1425b13afeb1">浏览器没有直接提供监听URL改变（push、pop、replace）的接口，因此 <code class="notion-inline-code">react-router</code> 对原生的 <code class="notion-inline-code">history</code> 对线进行了包装，提供了监听URL改变的API。</div><div class="notion-text notion-block-89547db7c4fb44c5a8923184dfbd76e2">使用 <code class="notion-inline-code">react-router</code> 时不需操作History对象（<code class="notion-inline-code">Routes</code> 组件会进行操作）</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-cbe382773d1c42f3a483689fdd06bb79" data-id="cbe382773d1c42f3a483689fdd06bb79"><span><div id="cbe382773d1c42f3a483689fdd06bb79" class="notion-header-anchor"></div><a class="notion-hash-link" href="#cbe382773d1c42f3a483689fdd06bb79" title="11.2 Location对象"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>11.2 Location对象</b></span></span></h4><div class="notion-text notion-block-22574aa1671b461abf82ca1792039f7f"><code class="notion-inline-code">react-router</code> 对 <code class="notion-inline-code">window.location</code> 进行包装后，提供了一个形式简洁的Location对象，形如：</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-8f55211f21d94a73979e5579540cb712" data-id="8f55211f21d94a73979e5579540cb712"><span><div id="8f55211f21d94a73979e5579540cb712" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8f55211f21d94a73979e5579540cb712" title="state"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>state</b></span></span></h4><div class="notion-text notion-block-f1b8f015dcec4d1d8ecbb5466994bcfc">不显示在页面上，不会引起刷新，只由开发人员操作。</div><div class="notion-text notion-block-7aab23dd0ca3499e92dba95837442f6d">可用于记录用户的跳转详情（从哪跳到当前页面）或在跳转时携带信息。</div><div class="notion-text notion-block-57ad5e96420b484bbf3c9f9c87738acb">可以用在 <code class="notion-inline-code">Link</code> 组件或 <code class="notion-inline-code">navigate</code> 方法中</div><div class="notion-text notion-block-bde9e0ccf61f434fb1e47f99ead1cf57">在目标的组件中，可以用 <code class="notion-inline-code">useLocation</code> 方法获取该对象</div><blockquote class="notion-quote notion-block-759b9101befc41b29dd13aafe42758e5"><div>state中的信息会进行序列化，因此如日期对象等信息会变为string</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-94744f2121724446a8e749de6782da4d" data-id="94744f2121724446a8e749de6782da4d"><span><div id="94744f2121724446a8e749de6782da4d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#94744f2121724446a8e749de6782da4d" title="key"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>key</b></span></span></h4><div class="notion-text notion-block-5c3f12004e744f079fa1db36fd90e4c4">每个Location对象拥有一个唯一的key，可以据此来实现基于Location的滚动管理，或是数据缓存。</div><div class="notion-text notion-block-11bc07833184498ab45cc3b893b5c00c">如：将 <code class="notion-inline-code">location.key</code> 和 URL 作为键，每次请求数据前，先查找缓存是否存在来判断是否实际发送请求，来实现客户端数据缓存。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-d2bbff95b9d747af9bcc96f57b0c5607" data-id="d2bbff95b9d747af9bcc96f57b0c5607"><span><div id="d2bbff95b9d747af9bcc96f57b0c5607" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d2bbff95b9d747af9bcc96f57b0c5607" title="十二、 各类Router组件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>十二、 各类Router组件</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-8411af282fac4937849b7a8765f4249c" data-id="8411af282fac4937849b7a8765f4249c"><span><div id="8411af282fac4937849b7a8765f4249c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8411af282fac4937849b7a8765f4249c" title="12.1 HashRouter和BrowserRouter的区别"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.1 HashRouter和BrowserRouter的区别</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-1f738bea466b48b099da8157b8c1b331"><li><code class="notion-inline-code">HashRouter</code> 只会修改URL中的哈希值部分；而 <code class="notion-inline-code">BrowserRouter</code> 修改的是URL本身</li></ul><ul class="notion-list notion-list-disc notion-block-011972ef95884db7a06a3550b1c5a085"><li><code class="notion-inline-code">HashRouter</code> 是<b>纯前端</b>路由，可以通过输入URL直接访问；使用时 <code class="notion-inline-code">BrowserRouter</code> 直接输入URL会显示404，除非配置Nginx将请求指向对应的HTML文件。初次进入 <code class="notion-inline-code">/</code> 路径时或点击 <code class="notion-inline-code">Link</code> 组件跳转时不会发送请求</li></ul><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-d94383e1f53f459ca52cf2be1a1dd362" data-id="d94383e1f53f459ca52cf2be1a1dd362"><span><div id="d94383e1f53f459ca52cf2be1a1dd362" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d94383e1f53f459ca52cf2be1a1dd362" title="12.2 unstable_HistoryRouter"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.2 unstable_HistoryRouter</b></span></span></h4><div class="notion-text notion-block-2e9f8022d0774c50a8dfab19eb26bf72">使用 <code class="notion-inline-code">unstable_HistoryRouter</code> 需要传入一个 <code class="notion-inline-code">history</code> 库的实例，这将允许在非react作用于下操作history对象。</div><blockquote class="notion-quote notion-block-948ae91e836543d49aee8f504c3aacd0"><div>由于项目使用的history和react-router中使用的history版本可能不一样，该API目前标为unstable状态</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-8b3d04ccd5654712be586275ec0e5ea6" data-id="8b3d04ccd5654712be586275ec0e5ea6"><span><div id="8b3d04ccd5654712be586275ec0e5ea6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8b3d04ccd5654712be586275ec0e5ea6" title="12.3 MemoryRouter"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.3 MemoryRouter</b></span></span></h4><div class="notion-text notion-block-6c83cf5b1a9e4292be2aa0321b93afa8"><code class="notion-inline-code">HashRouter</code> 和 <code class="notion-inline-code">BrowserRouter</code> 都是依据外部对象（history）进行导航，而 <code class="notion-inline-code">MemoryRouter</code> 则是自己存储和管理状态堆栈，多用于测试场景。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-c282d5574d9e40c6ab2e13949c13e01a" data-id="c282d5574d9e40c6ab2e13949c13e01a"><span><div id="c282d5574d9e40c6ab2e13949c13e01a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c282d5574d9e40c6ab2e13949c13e01a" title="12.4 NativeRouter"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.4 NativeRouter</b></span></span></h4><div class="notion-text notion-block-5e3c27529a5c462d805957226938169a">推荐的用于 React Native的Router组件</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-61bd834c0ca94f05a7affe05e1640b61" data-id="61bd834c0ca94f05a7affe05e1640b61"><span><div id="61bd834c0ca94f05a7affe05e1640b61" class="notion-header-anchor"></div><a class="notion-hash-link" href="#61bd834c0ca94f05a7affe05e1640b61" title="12.5 StaticRouter"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>12.5 StaticRouter</b></span></span></h4><div class="notion-text notion-block-2b38472b29f54f9399be79f0b3a30572">在nodejs端使用，渲染react应用。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e517dfd47d0743cf9291f89b598802af" data-id="e517dfd47d0743cf9291f89b598802af"><span><div id="e517dfd47d0743cf9291f89b598802af" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e517dfd47d0743cf9291f89b598802af" title="十三、使用JS对象定义路由（路由表）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>十三、使用JS对象定义路由（路由表）</b></span></span></h4><div class="notion-text notion-block-dc46876d46c94737a236b23c1bbc50de">使用 <code class="notion-inline-code">useRoutes</code> hook，可以使用一个JS对象而不是Routes组件与Route组件来定义路由。其功能类似于<a target="_blank" rel="noopener noreferrer" class="notion-link" href="https://link.juejin.cn/?target=https%3A%2F%2Flink.zhihu.com%2F%3Ftarget%3Dhttps%3A%2F%2Fwww.npmjs.com%2Fpackage%2Freact-router-config">react-router-config(opens new window)</a></div><div class="notion-text notion-block-12734c2fb8b644f7a9fe8159c5ae6eb8"><code class="notion-inline-code">useRoutes</code> 的返回是 React Element，或是 null。</div><div class="notion-text notion-block-ca3df618964943538658f13ff05d65b6">此功能用来管理路由表，相比v5，可能需要借助一些第三方库来实现路由config管理，现在v6版本自带</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-aba7c921ecee4066810b4b4a9bdab349" data-id="aba7c921ecee4066810b4b4a9bdab349"><span><div id="aba7c921ecee4066810b4b4a9bdab349" class="notion-header-anchor"></div><a class="notion-hash-link" href="#aba7c921ecee4066810b4b4a9bdab349" title="(一) 创建路由表"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>(一) 创建路由表</b></span></span></h4><div class="notion-text notion-block-debfbff65c6f4c5188e552b05649411f">对于传入的配置对象， 其类型定义如下：</div><div class="notion-text notion-block-4875d8b5873f4d7cb8e623d20aac6e1f">提示</div><div class="notion-text notion-block-f08c52c4dcaa4e218fafa38fd7487e1f">也可以单独创建 routes 文件夹管理路由表，然后在组件内使用 useRoutes</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-af99610d3d844fdba9b4dee849b024f0" data-id="af99610d3d844fdba9b4dee849b024f0"><span><div id="af99610d3d844fdba9b4dee849b024f0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#af99610d3d844fdba9b4dee849b024f0" title="(二) 组件结构内使用函数返回值作为占位符"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>(二) 组件结构内使用函数返回值作为占位符</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-a5cac14369df4f5c9dd2de3b0215226e" data-id="a5cac14369df4f5c9dd2de3b0215226e"><span><div id="a5cac14369df4f5c9dd2de3b0215226e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a5cac14369df4f5c9dd2de3b0215226e" title="(三) 嵌套路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>(三) 嵌套路由</b></span></span></h4><blockquote class="notion-quote notion-block-757563d8abec42dfaeeaf967c502451e"><div>在一级路由下面创建二级子路由</div></blockquote><ol start="1" class="notion-list notion-list-numbered notion-block-44820430adad48c59587d22cb9429dac"><li>引入路由路由占位符OutLet到组件中</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-16d4b2d8be854aad88ce06ac4f8d79ff"><li>引入NavLink到组件中改变路径，子路由路径可以不需要加<code class="notion-inline-code">/</code></li></ol><div class="notion-text notion-block-1f9184189ded4bd3a987999d7361de0a">注意</div><div class="notion-text notion-block-b642bafce26e43e898a705edd3518643"><b>不要忘记使用Outlet作为占位符</b></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-500704e254b04887b9649b9c5004a980" data-id="500704e254b04887b9649b9c5004a980"><span><div id="500704e254b04887b9649b9c5004a980" class="notion-header-anchor"></div><a class="notion-hash-link" href="#500704e254b04887b9649b9c5004a980" title="(四) 路由懒加载"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>(四) 路由懒加载</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-dda63fe931054ef2b012138d97b7ab5b" data-id="dda63fe931054ef2b012138d97b7ab5b"><span><div id="dda63fe931054ef2b012138d97b7ab5b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#dda63fe931054ef2b012138d97b7ab5b" title="十四、其他hooks函数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>十四、其他hooks函数</b></span></span></h4><div class="notion-text notion-block-d81819f29445432ca4130284481a1c7e">直接在组件中调用即可</div><hr class="notion-hr notion-block-3b76b4b8ccd940beb4945b976149d389"/><blockquote class="notion-quote notion-block-ced1cc861386413984db64032170bf31"><div>useRouterContext</div></blockquote><div class="notion-text notion-block-6bed4affde644d428dbd818af0ac60fc">作用：判断组件是否被路由包裹</div><hr class="notion-hr notion-block-eafc527d6d694372b0a4262a1455c066"/><blockquote class="notion-quote notion-block-3756a863c09c446ca6cb56365fc20c20"><div>useNavigationType</div></blockquote><div class="notion-text notion-block-e03353bc43f24f06ab085814c9a4d113">作用：判断路由跳转方式</div><div class="notion-text notion-block-a19e2efd71424410966eb3ceba5d2af7">返回值：<code class="notion-inline-code">push</code> <code class="notion-inline-code">pop</code> <code class="notion-inline-code">replace</code></div><div class="notion-text notion-block-16dfa0507cd34066bb7597af8af64706">pop是在浏览器中直接打开了这个路由的组件</div><hr class="notion-hr notion-block-4734cf0d0ed6421aa3580174bd38303d"/><blockquote class="notion-quote notion-block-a5056bcdc9274a7a8dca9d4ce4e11beb"><div>useOutlet</div></blockquote><div class="notion-text notion-block-3b23dce30ffb4d7f960892786a6d2a37">作用：查看组件下级路由信息</div><div class="notion-text notion-block-6f4c3f81dfb44a7a8a38d6060d8ac1b7">组件若未被挂载则返回null，若以被挂载，则返回该子组件信息</div><hr class="notion-hr notion-block-4a70921c8e424699bb9385d84f0c5fd3"/><blockquote class="notion-quote notion-block-0a77cae220f54adeb43b10ca57853139"><div>useResolvePath</div></blockquote><div class="notion-text notion-block-1ed4b7038abd457aad66ec1685915ee1">作用：解析路径</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-13aa314fd07a4e819810e173ae21723f" data-id="13aa314fd07a4e819810e173ae21723f"><span><div id="13aa314fd07a4e819810e173ae21723f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#13aa314fd07a4e819810e173ae21723f" title="动态路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>动态路由</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-1e4ac23bc1da45ab975d9f6d41f8cbcb" data-id="1e4ac23bc1da45ab975d9f6d41f8cbcb"><span><div id="1e4ac23bc1da45ab975d9f6d41f8cbcb" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1e4ac23bc1da45ab975d9f6d41f8cbcb" title="router/index.ts 默认路由"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>router/index.ts 默认路由</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-58c00705ad1a4e369ce10fd80826db2e" data-id="58c00705ad1a4e369ce10fd80826db2e"><span><div id="58c00705ad1a4e369ce10fd80826db2e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#58c00705ad1a4e369ce10fd80826db2e" title="redux login/action.ts"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>redux login/action.ts</b></span></span></h4><div class="notion-text notion-block-e8c0e5fe5c8d4e87b440756124c800dc"><b>注意带 //import! 的标识</b> 每次导航列表更新时，再触发路由更新action handelFilterRouter 就是根据导航菜单列表 和权限列表 得出路由表的</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-08237d5f7af149ff9bfc4f8b827546a2" data-id="08237d5f7af149ff9bfc4f8b827546a2"><span><div id="08237d5f7af149ff9bfc4f8b827546a2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#08237d5f7af149ff9bfc4f8b827546a2" title="utils 工具函数处理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>utils 工具函数处理</b></span></span></h4><div class="notion-text notion-block-346305abc09a4aa2a5f1f6b53f731ebe">说一说我这里为什么要映射element 成对应组件这部操作，原因是我使用了redux-persist（redux持久化。</div><div class="notion-text notion-block-591623c999494a698f2fc9729dce498e">若是直接转换后存入本地再取出来渲染是会有问题的，所以需要先将element保存成映射路径，然后渲染前再进行一次路径映射出对应组件。</div><div class="notion-text notion-block-a0f956fb96744e5e9460055b20ddea5b"><b>每个后台的数据返回格式都不一样，需要自己去转换，我这里的转换仅供参考。</b> <b>ps:defaulyRoutes和默认router/index.ts导出是一样的，可以做个小优化，复用起来。</b></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-395883df051d41dd93413b4e42046bd5" data-id="395883df051d41dd93413b4e42046bd5"><span><div id="395883df051d41dd93413b4e42046bd5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#395883df051d41dd93413b4e42046bd5" title="App.tsx"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>App.tsx</b></span></span></h4><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-b2a553d0ed5c48d483a46670cf9d7f4c" data-id="b2a553d0ed5c48d483a46670cf9d7f4c"><span><div id="b2a553d0ed5c48d483a46670cf9d7f4c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b2a553d0ed5c48d483a46670cf9d7f4c" title="路由传参"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由传参</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-d9d7f16bb35e4d85a995b29e7e48b859" data-id="d9d7f16bb35e4d85a995b29e7e48b859"><span><div id="d9d7f16bb35e4d85a995b29e7e48b859" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d9d7f16bb35e4d85a995b29e7e48b859" title="1. params传参"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1. params传参</b></span></span></h4><div class="notion-text notion-block-cdfdc18469a641fba4f8e280e0a8828b">优点：刷新页面，参数不丢失</div><div class="notion-text notion-block-4cd4c845068245c183893ebeea64bcd9">缺点：1.只能传字符串，传值过多url会变得很长 2. 参数必须在路由上配置</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-680fbe085b344ebb928eea32dda49ba8" data-id="680fbe085b344ebb928eea32dda49ba8"><span><div id="680fbe085b344ebb928eea32dda49ba8" class="notion-header-anchor"></div><a class="notion-hash-link" href="#680fbe085b344ebb928eea32dda49ba8" title="路由配置"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由配置</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-e4fdd315b50c4ee29d7256aed66e656e" data-id="e4fdd315b50c4ee29d7256aed66e656e"><span><div id="e4fdd315b50c4ee29d7256aed66e656e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e4fdd315b50c4ee29d7256aed66e656e" title="路由跳转与获取路由参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由跳转与获取路由参数</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-7adecc052f69421ab77e0bc36e4970e1" data-id="7adecc052f69421ab77e0bc36e4970e1"><span><div id="7adecc052f69421ab77e0bc36e4970e1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7adecc052f69421ab77e0bc36e4970e1" title="2. search传参"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>2. search传参</b></span></span></h4><div class="notion-text notion-block-01fe20a5e03043c6af6563a190001ccc">优点：刷新页面，参数不丢失</div><div class="notion-text notion-block-777207eda9ec49039ff64f64e934751a">缺点：只能传字符串，传值过多url会变得很长，获取参数需要自定义hooks</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-136a7c5e74b9411a8f0f148b312a75b9" data-id="136a7c5e74b9411a8f0f148b312a75b9"><span><div id="136a7c5e74b9411a8f0f148b312a75b9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#136a7c5e74b9411a8f0f148b312a75b9" title="路由配置"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由配置</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ce8144ab62664cfca05de5567fdefc1d" data-id="ce8144ab62664cfca05de5567fdefc1d"><span><div id="ce8144ab62664cfca05de5567fdefc1d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ce8144ab62664cfca05de5567fdefc1d" title="路由跳转与获取路由参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由跳转与获取路由参数</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-5e0b37bb15684155834eb919eeffab0e" data-id="5e0b37bb15684155834eb919eeffab0e"><span><div id="5e0b37bb15684155834eb919eeffab0e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5e0b37bb15684155834eb919eeffab0e" title="3. state传参🙌"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>3. state传参🙌</b></span></span></h4><div class="notion-text notion-block-f656f92a0457419d9aa93da653b31f9c">优点：可以传对象</div><div class="notion-text notion-block-10df432b3d4b4a24bac3bb505e578ea7">缺点： <code class="notion-inline-code">&lt;HashRouter&gt;</code>刷新页面，参数丢失</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-d867ecacd5d24f9d96b7bab3178238d2" data-id="d867ecacd5d24f9d96b7bab3178238d2"><span><div id="d867ecacd5d24f9d96b7bab3178238d2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d867ecacd5d24f9d96b7bab3178238d2" title="路由配置"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由配置</b></span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-41a82fbd2cbf4710af7a811fb3a2f025" data-id="41a82fbd2cbf4710af7a811fb3a2f025"><span><div id="41a82fbd2cbf4710af7a811fb3a2f025" class="notion-header-anchor"></div><a class="notion-hash-link" href="#41a82fbd2cbf4710af7a811fb3a2f025" title="路由跳转与获取路由参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>路由跳转与获取路由参数</b></span></span></h4><div class="notion-text notion-block-508750696bec42eb98e8ebb63f15f45d">笔记</div><div class="notion-text notion-block-367831edebcc4149bf6a791d619e96dd"><code class="notion-inline-code">&lt;HashRouter&gt;</code> 不支持 <code class="notion-inline-code">location.key</code> 与 <code class="notion-inline-code">location.state</code>，<code class="notion-inline-code">&lt;HashRouter&gt;</code>通过<code class="notion-inline-code">state</code>传递参数，刷新页面后参数丢失，官方建议使用<code class="notion-inline-code">&lt;BrowserRouter&gt;</code>，<code class="notion-inline-code">&lt;BrowserRouter&gt;</code>页面刷新参数也不会丢失。</div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Docker笔记]]></title>
            <link>https://www.axin.work/article/cbb8505f-9daa-4474-b51b-6a11d96f3911</link>
            <guid>https://www.axin.work/article/cbb8505f-9daa-4474-b51b-6a11d96f3911</guid>
            <pubDate>Fri, 31 May 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-cbb8505f9daa4474b51b6a11d96f3911"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div></main></div>]]></content:encoded>
        </item>
    </channel>
</rss>