万字血书React—走近React
<h2 id="配置开发环境">配置开发环境</h2><p>脚手架工具create-react-app</p>
<p>储备知识:终端或命令行、代码编辑器</p>
<p>React官方中文文档</p>
<h3 id="create-react-app">create-react-app</h3>
<p>其是基于Node的快速搭建React项目的脚手架工具。</p>
<pre><code class="language-shell">npx create-react-app testdemo
cd testdemo
npm i
</code></pre>
<p>npx命令是npm v5.2.0引入的一条命令,无需安装脚手架包,就可以直接使用这个包提供的命令</p>
<p>yarn是Facebook发布的包管理器,功能与npm相同,具有快速、可靠和安全的特点</p>
<h3 id="react-with-typescript">React with TypeScript</h3>
<pre><code class="language-shell">npx create-react-app testdemo-ts --template typescript
cd testdemo
npm i
</code></pre>
<h4 id="about-typescript">About TypeScript</h4>
<ul>
<li>TypeScript是JavaScript的超集</li>
<li>给原生JavaScript添加类型检查</li>
<li>与ES6一样目前无法被主流浏览器直接读取</li>
</ul>
<h4 id="compile-typescript">Compile TypeScript</h4>
<p>编译器:ts-loader、awesome-typescript-loader以及<strong>babel-loader</strong></p>
<p>编译器配置文件:tsconfig.json</p>
<pre><code class="language-json">{
"compilerOptions": {
"noImplicitAny": false, //不需要显示地声明变量的类型any
"target": "es5", //编译后的目标js版本
"lib": [
"dom",
"dom.iterable",
"esnext"
], //库文件,过这些库文件,告诉typescript编译器可以使用哪些功能
"allowJs": true, //允许混合编译js文件
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true, //允许使用commonJs方式import默认文件
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext", //配置代码模块系统,Node.js的commonJs、ES6的esnext、requireJs的AMD
"moduleResolution": "node",// 决定编译器的工作方式
"resolveJsonModule": true,
"isolatedModules": true, //编译器会将每个文件作为单独的模块使用
"noEmit": true, //发生错误时候,编译器不会生成Js代码
"jsx": "react-jsx" //允许编译器支持编译react代码
},
"include": [
"src"
] //使用此选项列出我们需要编译的文件, “文件路径”选项需要文件的相对或绝对路径
}
</code></pre>
<h4 id="update-to-typescript">Update to TypeScript</h4>
<pre><code class="language-shell">1、npm install --save typescript @types/node @types/react @types/react-dom @types/jest
2、所有js文件改为jsx文件
3、import react
</code></pre>
<h2 id="react基础">React基础</h2>
<h3 id="about-react">About React</h3>
<h4 id="history-of-fe">History of FE</h4>
<p>HTML、CSS、JavaScript——Ajax——jQuery——Angular MVC——Vue、React MVVM</p>
<h4 id="why-is-react">Why is React?</h4>
<ul>
<li>单向数据流</li>
</ul>
<ol>
<li>你只需要描述UI(HTML)看起来是什么样子,就和写HTML一样</li>
<li>React负责渲染UI,并在数据变化时更新UI</li>
</ol>
<ul>
<li>虚拟DOM</li>
</ul>
<p>类似于Docker或VMware的Snapshot的快照技术</p>
<p><img src="https://img2023.cnblogs.com/blog/3059980/202303/3059980-20230328164054985-792512356.png" alt="image" loading="lazy"></p>
<ul>
<li>组件化</li>
</ul>
<ol>
<li>保持交互的一致性</li>
<li>保持视觉风格的统一</li>
<li>便于程序员之间的协作</li>
</ol>
<ul>
<li>学习一次,随意使用(必杀技)</li>
</ul>
<ol>
<li>使用React可以开发Web应用</li>
<li>使用React可以开发移动端原生应用(react-native)</li>
<li>使用React可以开发VR(虚拟现实)(react 360)</li>
</ol>
<h4 id="what-is-react">What is React?</h4>
<p><strong>React</strong>是一个用于<strong>构建用户界面</strong>(HTML页面)的<strong>JavaScript库</strong></p>
<p>主要用来写HTML页面,或构建Web应用</p>
<p>如果从MVC角度来看,React仅仅是视图层(V),只负责视图的渲染,不提供完整的M和C的功能</p>
<p>(经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。)</p>
<p>起源:Facebook的内部项目</p>
<h3 id="jsx">JSX</h3>
<h4 id="what-is-jsx">What is JSX?</h4>
<p>What's this?HTML?JS?</p>
<pre><code class="language-jsx">const element = <h1>Hello,world!</h1>
</code></pre>
<p>这是ReactJS自创的语言:JSX</p>
<ul>
<li>JSX不是标准的ECMAScript语法,只是语法扩展</li>
<li>对于React项目使用js和jsx都可以</li>
<li>ts对应tsx语法</li>
</ul>
<blockquote>
<p>拓展阅读:react-jsx、react-jsxdev</p>
</blockquote>
<p>JSX 其实是<code>React.createElement</code>的语法糖,下图的两种写法完全等价:<br>
<img src="https://img2023.cnblogs.com/blog/3059980/202303/3059980-20230328164044586-1013508096.png" alt="image" loading="lazy"></p>
<h4 id="why-is-jsx">Why is JSX?</h4>
<ul>
<li>React并不强制使用JSX,也可以使用原生的JavaScript</li>
<li>React认为视图的本质是:渲染逻辑与UI视图表现的内在统一</li>
<li>React把HTML与渲染逻辑进行了耦合,形成了JSX</li>
</ul>
<h4 id="features-of-jsx">Features of JSX</h4>
<ul>
<li>HTML代码可以与JSX兼容</li>
<li>可以在JSX中嵌入表达式</li>
<li>使用JSX指定子元素</li>
</ul>
<h4 id="attention">Attention</h4>
<ul>
<li>React元素的属性名使用<strong>小驼峰</strong>命名法</li>
<li>特殊的属性名:class->className、for->htmlFor、tabindex->tabIndex</li>
<li>如果元素没有子节点可以用<code>/></code>结束</li>
<li>推荐使用<strong>小括号包裹JSX</strong>,从而避免JS中的自动插入分号陷阱</li>
</ul>
<h4 id="基本使用">基本使用</h4>
<h5 id="jxs中使用嵌入js表达式">JXS中使用(嵌入)Js表达式</h5>
<p>数据存储在JS中,语法:{JavaScript表达式} 注意:语法是<strong>单大括号</strong></p>
<pre><code class="language-jsx">const name = '张三'
// 1、使用JSX创建react元素
const title = <h1>Hello {name}</h1>
//2、渲染react元素
ReactDOM.render(title, document.getElementById('root'))
</code></pre>
<p>React DOM 在渲染所有输入内容之前,默认会进行<strong>转义</strong>。它可以确保在你的应用中,永远不会注入那些并非自己明确编写的内容。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 <strong>XSS(cross-site-scripting, 跨站脚本)</strong>攻击。</p>
<blockquote>
<p>拓展阅读:如何防止XSS攻击?</p>
</blockquote>
<h5 id="jsx的条件渲染">JSX的条件渲染</h5>
<ul>
<li>场景:loading效果</li>
<li>条件渲染:根据条件渲染特点的JSX结构</li>
<li>可以使用<strong>if/else</strong>或三元运算符或<strong>逻辑与运算符</strong>来实现</li>
</ul>
<pre><code class="language-jsx">const loadData = () => {
if (loading) {
return <div>loading...</div>
}
return <div>数据加载完成</div>
}
</code></pre>
<h5 id="jsx的列表渲染">JSX的列表渲染</h5>
<ul>
<li>应该使用数组的<strong>map()</strong>方法(映射)</li>
<li>渲染列表时应该添加key属性,<strong>key属性的值要保证唯一</strong></li>
<li>原则:map()遍历谁,就给谁加key属性</li>
<li>注意:<strong>尽量避免使用索引号作为key</strong></li>
</ul>
<pre><code class="language-jsx">const songs = [
{ id: 1, name: '爱你' },
{ id: 2, name: '年少有为' },
{ id: 3, name: '南山南' },
]
// 1、使用JSX创建react元素
const list = (
<ul>
{songs.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
)
</code></pre>
<h5 id="jsx的样式处理">JSX的样式处理</h5>
<blockquote>
<p>详见:React的行内样式与CSS</p>
</blockquote>
<h3 id="css-of-react">CSS of React</h3>
<h4 id="the-way-of-import-css-file">The way of import css file</h4>
<ul>
<li>直接引入整个css文件</li>
</ul>
<pre><code class="language-jsx">import './index.css'
<div className="app">
</code></pre>
<p>使用简单,但可能会造成样式的全局污染和样式冲突。</p>
<ul>
<li>JSS模块化引入组件</li>
</ul>
<pre><code class="language-jsx">import style from './index.css'
<div className={style.app}>
</code></pre>
<p>需要额外配置,ts环境需要配置<code>*.d.ts</code>的类型声明文件</p>
<pre><code class="language-ts">declare module "*.css" {
const css: {
: string //约定:导出key所在的对象,原始的类名和内容都会和转化为这个对象
};
export default css;
}
</code></pre>
<h4 id="css-modulejss">CSS module/JSS</h4>
<ul>
<li>每个jsx或tsx文件被视为一个独立存在的原件</li>
<li>原件所包含的所有内容也同样都应该是独立存在的</li>
</ul>
<blockquote>
<p>拓展阅读:CSS in Js</p>
</blockquote>
<h4 id="css--typescript">CSS & TypeScript</h4>
<p>Ts的优势就是给Js进行类型检查,那么通过JSS将CSS转换为Js对象,是不是也可以给CSS添加类型?</p>
<p>插件:<code>typescript-plugin-css-modules</code></p>
<pre><code class="language-shell">npm i typescript-plugin-css-modules --save-dev
</code></pre>
<p>在tsconfig.json文件compilerOptions新增:</p>
<pre><code class="language-json">"plugins": [{
"name":"typescript-plugin-css-modules"
}]
</code></pre>
<p>新建.vscode文件夹——新建文件settings</p>
<pre><code class="language-js">{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
</code></pre>
<p>配置后会发现编写style也会有只能提示</p>
<h3 id="media--fonts">Media & fonts</h3>
<pre><code>src/assets/images
src/assets/fonts
src/assets/icons
</code></pre>
<h3 id="state--props">State & Props</h3>
<h4 id="difference">Difference</h4>
<ul>
<li>props是组件对外的接口,而state是组件对内的接口</li>
<li>props用于组件间的数据传递,而state用于组件内部的数据传递</li>
</ul>
<h4 id="state">State</h4>
<p>State是组件的“私有属性”</p>
<p><strong>初始化</strong></p>
<pre><code class="language-tsx">//构造函数constructor是唯一可以初始化state的地方
constructor(props){
super(props);
this.state = {
count: 0
}
}
</code></pre>
<p><strong>修改</strong></p>
<pre><code class="language-jsx">//使用setState()修改数据,更新组件状态,调用render函数重新渲染
onClick = {() => {
this.setState({isOpen: !this.state.isOpen});
}}
</code></pre>
<p><strong>异步更新 同步执行</strong></p>
<p>调用setState后,state不会立即改变,是异步操作(React会将多个修改合并为一个)。所以,不要依赖当前的State,计算下个State。</p>
<p>setState本身并非异步,但对state的处理机制给人一种异步的假象。</p>
<pre><code class="language-js">onClick = {() => {
this.setState((preState, preProps) => {
return {count: preState.count + 1}
},() => {
console.log("count" ,this.state.conut)
});
this.setState((preState, preProps) => {
return {count: preState.count + 1}
},() => {
console.log("count" ,this.state.conut)
});
}}
</code></pre>
<h4 id="props">Props</h4>
<p>本质上,props就是传入函数的参数,是父组件传向子组件的数据。</p>
<p><strong>父组件</strong></p>
<pre><code class="language-tsx"><ul>
{robots.map(r => <Robot id={r.id} name={r.name} email={r.email}></Robot>)}
</ul>
</code></pre>
<p><strong>子组件</strong></p>
<pre><code class="language-tsx">//为Robot指定类型React.FC,FC(functional component)函数式组件的接口,接受泛型参数P(Props)
const Robot: React.FC<RobotProps> = (props) => {
const id = props.id;
const name = props.name;
const email = props.email;
return (<div className={styles.cardContainer}>
<img src={`https://robohash.org/${id}`} alt="robot" />
<h2>{name}</h2>
<p>{email}</p>
</div>
);
}
</code></pre>
<p><strong>Immutable</strong></p>
<p>props是<strong>只读的</strong>,一旦创建不可被改变,只能通过销毁、重建来改变数据。</p>
<blockquote>
<p>优点:通过判断内存是否一致,来确认对象是否有经过修改,极大提高性能效率</p>
</blockquote>
<p>使用<strong>Immutable</strong>来编写程序的方式就是函数式编程(组件)。</p><br><br>
来源:https://www.cnblogs.com/gfhcg/p/17265829.html
頁:
[1]