React学习笔记 - 起手式

387 阅读3分钟

引入React

1、从 CDN 引入

CDN 引入比较麻烦,注意以下顺序

<script src="https://.../react.xxx.min.js"></script>
<script src="https://.../react-dom.xxx.min.js"></script>
  1. 引入 React
  2. 引入 ReactDOM

cjs 版和 umd 版的区别:

  • cjs 全称 CommonJS,是 Node.js 支持的模块规范语法
  • umd 是统一模块定义,兼容各种模块规范(Node.js、浏览器等),优先使用 umd
  • 最新的模块规范是使用 import、export 关键字

2、通过 webpack 引入

安装 yarn add react react-dom

然后import:

import React from 'react'
import ReactDOM from 'react-dom'
  • 这样的引入方式需要配置好 webpack
  • 除了用 webpack ,也可以用 rollup、parcel 等工具

webpack 的配置较麻烦,React 提供了 create-react-app 工具来代替,即:

  • 新手用 create-react-app
  • 老手用 webpack/rollup

用 React 实现 +1 demo

const root = document.querySelector("#app")
let n = 0
const App = ()=>React.createElement("div", {className:"red"}, [
    n,
    React.createElement(
    	"button",
        {
            onClick(){
                n += 1
                ReactDOM.render(App(), root)
            }
        },
        "+1"
    )
])

ReactDOM.render(App(), root)  //渲染到页面

说明

App1 = React.createElement("div", null, n) ---- React 元素

App2 = ()=>React.createElement("div", null, n) ---- React 函数组件

  • 虚拟DOM

React.createElement的返回值看似是一个 DOM 对象,但实际上并不是真正的 DOM,称为虚拟 DOM 对象

  • DOM Diff 算法

通常用函数组件的形式 App2 来生成虚拟DOM,当数据变化时,再次运行App2()可得到新的虚拟DOM,React 会对比新旧两个虚拟 DOM,找出不同,然后局部更新视图。找不同的算法称为 DOM Diff 算法

这种写法过于复杂!!

JSX -- JS 扩展版

何为 JSX

1、与 Vue 的 .vue 文件类比

JSX 是对上述 JS 的一种简化写法,可类比 Vue 的 .vue 文件

  • Vue 有 .vue 文件:

用 vue-loader 转译 .vue 文件(编译原理),将简单的 <template> 写法转译为复杂的 render 函数的形式

  • 同理,React 有 JSX:

用 jsx-loader 转译 JSX,jsx-loader 已经被 babel-loader 取代,且内置到 webpack 中

2、JSX 对 React 元素的简化

  • JS 写法的虚拟 DOM:const element = React.createElement("div", {className: "xxx"}, "n")

  • JSX 写法的虚拟 DOM(直接写 XML 标签):const element = <div className="xxx">n</div>

babel-loader 可将 JSX 写法转为 JS 写法

使用 JSX

方法一:CDN

  • 引入 babel.js

  • <script type="text/babel"></script> 标签中写 JSX 代码

示例(+1 demo):

<!DOCTYPE html>
<html>
	...
    <script src="https://.../react.xxx.min.js"></script>
	<script src="https://.../react-dom.xxx.min.js"></script>
    <script src="https://.../babel.min.js"></script>
    <script type="text/babel">
    	// 以下为 JSX 代码
    	let n = 0
    	let fn = ()=>{
    		n+=1
    		ReactDOM.render(<App />, document.querySelector("#app"))
    	}
    	const App = () => (
    		<div>
        		<button onClick={fn}>+1</button>
        	</div>
    	)
    	ReactDOM.render(<App />, document.querySelector("#app"))
    </script>
</html>

工作原理:

babel.js<script type="text/babel"> 转译为 JS,并替换掉原 <script>

CDN 方法效率很低(原因如下),不推荐使用!

  • 需要下载 babel.js
  • 需要在浏览器端将 JSX 转译为 JS

这些工作完全可以在 build 时完成

方法二:webpack + babel-loader

需要配置,新手不建议

方法三:create-react-app

安装:yarn global add create-react-app

创建目录:create-react-app react-demo

示例

App.js 导出一个 React 函数组件:

import React from "react"
const App = ()=>{
  return (
    <div>一个App组件</div>
  )
}

export default App

由于 webpack 默认会用 babel-loader 处理 JS 文件,而 JSX 也需要用 babel-loader 处理,所以可以直接在 App.js 中使用 JSX 的语法,无需命名为 App.jsx。

在 index.js 引入:

import React from "react"
import ReactDOM from "react-dom"
import App from './App.js'

ReactDOM.render(<App />, document.querySelector("#app"))

JSX 基本语法总结

  • JSX 中 XML 标签可以视为一种值的类型,如 <div>hello JSX</div>,表示一个虚拟 DOM 对象,它相当于 React.createElement("div", null, "hello JSX")

  • 在标签内取变量或其他 JS 表达式要用 {} 包围 :

    • <div> {n} </div>
    • <div> {fn()} </div>
  • 标签上可直接写 DOM 的属性(并非 HTML 标签的属性)

    • <div className="xxx"> ---- 属性值为字符串,直接用引号
    • <div onClick={fn}> ---- 属性值为 JS 表达式,要用 {} 包围
  • return 语句要习惯性地加上 () --- 防止 return undefined ,例如:

function App(){
    return
    <div>
        ...
    </div>
}  //这样会return undefined