目录
- 如何引入React
- 函数的本质——延迟
- JSX的用法
- 条件判断与循环
1.如何引入React
1.1 CDN引入(很麻烦,没人用)
-
操作
1.需要引入两个库,注意顺序
2.react、react-dom
—react.development.js
—react-dom.development.js
3.引入这两个库之后就可以使用自己的JS文件 -
项目默认可以使用parcel来运行
// 对象
console.log(window.React);
// 函数
console.log(window.React.createElement);
// 对象
console.log(window.ReactDOM);
// 函数
console.log(window.ReactDOM.render);
- cjs和umd的区别
1.cjs全称CommonJS,是 Node.js 支持的模块规范
2.umd是统一模块定义,兼容各种模块规范
2.理论上优先使用umd.同时支持Node.js和浏览器
4.最新的模块规范是使用 import 和 export 关键字 - 模块规范
如何声明一个模块
1.直接写代码 const
2.然后导出 export Default 函数名
3.这就是声明一个可以被别人导入的模块
1.2 webpack引入React(了解)
- import…from…
1.yarn add react react-dom
2.import Read from 'react'
3.import ReactDOM from 'react-dom'
注意大小写
也很麻烦,需要配置webpack - 使用:
create-react-app
代替
1.3 如何正确引入React
- 新人:
create-react-app
老手:webpack/rollup
自己配置 - 安装
yarn global add create-react-app
不用npx,在window上兼容性不好 - 新建文件
create-react-app my-app
cd my-app
yarn start
start . //打开当前文件夹
2.用React实现+1
-
CDN引入的React都会变成全局变量
window.React
-
使用React创建一个div
const App = window.React.createElement('div',{className:'red'},n)
1.创建一个div,class为red,里面内容为n
2.元素属性放到第二个参数,内容用 { } 括起来
3.所有div里面的东西都放到第三个参数中,内容可以用 [ ] 括起来 -
ReactDOM.render(App(), root)
1.将App渲染到页面中的root元素中
2.root = document.querySelector('#root')
-
多个
React.createElement
可以嵌套
1.也就是在div里可以创建一个button,然后通过点击事件修改n的值
2.此时 App 需要变为函数 -
一个小tip
JS中设置class就是用className,class是一个关键字
//多个createElement嵌套使用
//创建一个class为red的div,里面内容为n和一个添加了点击事件监听的button
const App = () => React.createElement("div", { className: "red" }, [ n,
React.createElement( "button", { onClick: () => {
n += 1;
//这里调用App的返回值div,会重新读n的值
ReactDOM.render(App(), root);
}
},"+1")
]);
2.1 App为什么要变成函数
- 一开始采用 App 为一个表示 div 的对象,里面包含button
渲染:ReactDOM.render(App, root);
- 问题:即使添加了onClick事件,但依旧没办法执行+1操作
- 原因:
1.当App是一个对象的时候(App = React.create…),赋值即会就计算出 n 的值,此时 n=0。
2.然后进行点击事件后 n 虽然此时为1,对象 App 中的 0 已经和 n 无关了,因为已经赋值过了
3.因此要将 App 变成函数
——ReactDOM.render(App(), root);
4.render 的是 App函数 返回的 div,调用App函数的时候会重新去读 n 的值,就能得到最新的n
2.2 6个6
let i
for(i=0;i<6;i++){
setTimeout(()=>{console.log(i)},1000)
}
- 一秒钟之后打印出6个6,因为函数执行时遇到外部变量会去读取其最新的值
1.函数是在调用的时候执行
2.也就是调用的时候去计算 i - setTimeout(fn,1000)
请在1000ms之后,尽快执行fn
不是在1000ms之后执行fn,注意区别 - 解法一:语法糖
for(let i = 0 ; i<6 ; i++)
相当于:在函数作用域内声明一个中间变量 j
1.let j = i ; 打印出 j
2.当 i 不同时,函数作用域不同,则局部变量 j 为不同的值,就不会被之前的值替代,因此由6个 j,打印出来则不同
(全局变量只有一个,局部变量可以有多个)
3.JS根据这个思路创造了这个语法糖 - 解法二:用立即执行函数
1.写一个函数,立即执行:!function(j){}(i)
2.在前面加一个感叹号,就可以阻止报错
3.给函数传一个实际参数 i,那函数就会把i的值复制给形式参数 j
4.这里 j 和 i 只是复制值的关系,没什么其他关系,因此 j 也可以取名 i,利用复制值的关系留下了i的值
for(var i=0;i<6;i++){
!function(j){
setTimeout(()=>{console.log(j)},1000)
}(i)
}
2.3 函数与延迟执行
- 普通代码
let b = 1+a - 函数
let f = ()=>1+a
let b = f()
函数相当于把1+a包起来,需要的时候再取值 - 区别
1.普通代码:立即求值,读取a当前的值
2.函数会等调用时再求值,即延迟求值。且求值时才会读取a的最新值
2.4 React元素和函数组件
- 对比
App1 = React.createElement('div',null,n)
:App1 是一个 React 元素
App2 = ()=> React.createElement('div',null,n)
:App2 是一个 React 函数组件 - 启示
1.函数App2是延迟执行代码,会在被调用的时候执行
2.这里的说是代码执行的时机,不是说同步和异步
(同步和异步:关注的是得到结果的时机)
3.小结
- React 元素
1.createElement 的返回值 element 可以代表一个 div
2.但 element 并不是真正的 div(DOM对象)
3.所以一般称 element 为 虚拟DOM 对象
——需要配合 ReactDom.render 使用 - ()=> React 元素
1.返回 element 的函数,也可以代表一个 div
2.这个函数可以多次执行,每次得到一个最新的 虚拟div
3.React 会对比两个 虚拟div,找出不同,局部更新视图
——不需要页面整体替换
4.找不同的算法叫做:DOM Diff 算法 - 虚拟DOM比真实的操作DOM快得多,因为是模拟的DOM对象