介绍
react 用于构建用户界面的 JavaScript 库
react 是一个将数据渲染为 HTML 视图的开源 JavaScript 库
react的特点:
- 声明式编码
- 组件化编码
- React Native 编写原生应用
- 高效(优秀的Diffing算法)
命令式编码, 就像准备晚餐, 你需要购买食材、切割食材、烹饪、调味、上菜等, 最后才能吃上饭
声明式编码, 就像去一家餐厅, 只需要告诉服务员, 我想要吃啥, 服务员就会让厨师给你准备好, 直接吃饭
入门
babel的作用:
ES6 => ES5
js => jsx
import => require
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>hello_react</title> </head> <body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> const VDOM = <h1>Hello, React</h1> ReactDOM.render(VDOM, document.getElementById('test')) </script> </body> </html>
|
虚拟DOM的两种创建方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>1_使用jsx创建虚拟DOM</title> </head> <body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> const VDOM = ( <h1 id="title"> <span>Hello, React</span> </h1> ) ReactDOM.render(VDOM, document.getElementById('test')) </script> </body> </html>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>2_使用js创建虚拟DOM</title> </head> <body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript"> const VDOM = React.createElement('h1', {id: 'title'}, React.createElement('span', {}, 'Hello,React')) ReactDOM.render(VDOM, document.getElementById('test')) </script> </body> </html>
|
当如果嵌套的标签多了, 使用原生的js, 实现起来就比较麻烦了
这时候采用jsx看起来就比较简洁
在使用jsx语法写标签的时候, 可以采用()
进行包裹多个标签
虚拟DOM与真实DOM
虚拟DOM其实就是一个普通的Object对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3_虚拟DOM与真实DOM</title> </head> <body> <div id="test"></div> <div id="demo"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> const VDOM = ( <h1 id="title"> <span>Hello, React</span> </h1> ) ReactDOM.render(VDOM, document.getElementById('test'))
const TDOM = document.getElementById('demo') console.log('虚拟DOM', VDOM); console.log('真实DOM', TDOM); debugger console.log(typeof VDOM); console.log(VDOM instanceof Object);
</script> </body> </html>
|
jsx语法规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>jsx语法规则</title> <style> .title { background-color: orange; width: 200px; } </style> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
const myId = 'aTgUiGu' const myData = 'HeLlo,rEaCt'
// 1.创建虚拟DOM const VDOM = ( <div> <h2 className="title" id={myId.toLocaleLowerCase()}> <span style={{ color: 'white', fontSize: '29px' }}>{myData.toLocaleLowerCase()}</span> </h2> <h2 className="title" id={myId.toLocaleLowerCase()}> <span style={{ color: 'white', fontSize: '29px' }}>{myData.toLocaleLowerCase()}</span> </h2> <input type="text" /> {/* <good>123</good> */} </div> ) // 2.渲染虚拟DOM到页面 ReactDOM.render(VDOM, document.getElementById('test'))
/* jsx语法规则: 1.定义虚拟DOM时,不要写引号。 2.标签中混入JS表达式时要用{}。 3.样式的类名指定不要用class,要用className。 4.内联样式,要用style={{key:value}}的形式去写。 5.只有一个根标签 6.标签必须闭合 7.标签首字母 (1).若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错。 (2).若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。
*/ </script> </body>
</html>
|
这段代码中, 外层{}
表示里头是一个js表达式 , 里头{}
表示的是一个js对象
fontSize
需要使用小驼峰的形式表示
<span style={{ color: 'white', fontSize: '29px' }}></span>
jsx小练习
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>jsx语法规则</title> <style> .title { background-color: orange; width: 200px; } </style> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
const data = ['Angular', 'React', 'Vue'] const VDOM = ( <div> <h1>前端js框架列表</h1> <ul> { data.map((item, index) => { return <li key={index}>{item}</li> }) } </ul> </div> ) ReactDOM.render(VDOM, document.getElementById('test')) </script> </body>
</html>
|
开发者工具安装
安装路径:
https://chromewebstore.google.com/search/react
浏览美团官网
Components
观察网页有多少个组件和组件的属性
Profiler
记录网站的一些性能, 渲染用了多久, 哪一个组件加载最慢
函数名就是组件名
类式名就是组件名
react中定义组件
函数式组件
babel在进行翻译的时候, 会开启严格模式, 禁止自定义的函数中的this指向window
this输出得到的是undefined, 这是因为严格模式下, this的指向不再是window了, this指向的是undefined
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>1_函数式组件</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> function MyComponent() { console.log(this); return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2> } ReactDOM.render(<MyComponent/>, document.getElementById('test'))
</script> </body>
</html>
|
类的基本知识(复习)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>1_类的基本知识</title> </head>
<body> <script type="text/javascript"> class Person { constructor(name, age) { this.name = name this.age = age } speak() { console.log(`我叫${this.name}, 我的年龄是${this.age}`); } }
class Student extends Person { constructor(name, age, grade) { super(name, age) this.grade = grade this.school = '尚硅谷' }
speak() { console.log(`我叫${this.name}, 我的年龄是${this.age}, 我读的是${this.grade}年级`); this.study() } study() { console.log('我很努力的学习'); } }
const s1 = new Student('小张', 15, '高一') console.log(s1); s1.speak() s1.study()
</script> </body>
</html>
|
类式组件
函数名就是组件名
类式名就是组件名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>2_类式组件</title> </head> <body> <div id="test"></div> <script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class MyComponent extends React.Component { render() { console.log('render中的this:',this); return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2> } } ReactDOM.render(<MyComponent/>, document.getElementById('test'))
</script> </body> </html>
|
有状态称为复杂组件, 无状态的称为简单组件
组件三大核心属性
原生事件绑定(复习)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>2_原生事件绑定</title> </head> <body> <button id="btn1">按钮1</button> <button id="btn2">按钮2</button> <button onclick="demo()">按钮3</button>
<script type="text/javascript"> const btn1 = document.getElementById('btn1') btn1.addEventListener('click', () => { alert('按钮1被点击了') })
const btn2 = document.getElementById('btn2') btn2.onclick = () => { alert('按钮2被点击了') }
function demo() { alert('按钮3被点击了') }
</script> </body> </html>
|
类方法中的this指向(复习)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head>
<body> <script type="text/javascript"> class Person { constructor(name, age) { this.name = name this.age = age }
study() { console.log(this); } } const p1 = new Person('tom', 18) p1.study() const x = p1.study x() </script> </body>
</html>
|
state
react中的事件绑定
严格模式下的, 普通函数this指向的是undefined
解决类中this指向问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>state</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Weather extends React.Component { constructor(props) { super(props) this.state = { isHot: true } this.changeWeather = this.changeWeather.bind(this) } render() { const { isHot } = this.state return ( <h2 id="title" onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}</h2> ) } changeWeather() { console.log(this); } } ReactDOM.render(<Weather />, document.getElementById('test'))
</script> </body>
</html>
|
state的用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>state</title> </head> <body> <div id="test"></div> <script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Weather extends React.Component{ constructor(props){ console.log('constructor'); super(props) this.state = {isHot:false,wind:'微风'} this.changeWeather = this.changeWeather.bind(this) }
render(){ console.log('render'); const {isHot,wind} = this.state return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1> }
changeWeather(){ console.log('changeWeather'); const isHot = this.state.isHot this.setState({isHot:!isHot}) console.log(this);
} } ReactDOM.render(<Weather/>,document.getElementById('test')) </script> </body> </html>
|
在类中直接编写赋值语句, 会将该属性放在实例对象身上
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Car { constructor(name, price) { this.name = name this.price = price } a = 1 wheel = 4 } const c1 = new Car('奔驰c63', 199) const c2 = new Car('宝马', 299) console.log(c1); console.log(c2);
|
state的简写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>state</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Weather extends React.Component { state = { isHot: true, wind: '微风' }
render() { const { isHot, wind } = this.state return ( <h2 id="title" onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}, {wind}</h2> ) }
changeWeather = ()=>{ console.log(this); const isHot = this.state.isHot this.setState({isHot: !isHot}) } } ReactDOM.render(<Weather />, document.getElementById('test')) </script> </body>
</html>
|
总结:
理解
1.state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
2.组件被称为”状态机”, 通过更新组件的state来更新对应的页面显示(重新渲染组件)
强烈注意
1.组件中render方法中的this为组件实例对象
2.组件自定义的方法中this为undefined,如何解决?
(a)强制绑定this: 通过函数对象的bind()
(b)箭头函数
3.状态数据,不能直接修改或更新
props
props的基本使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>1_props基本使用</title> </head>
<body> <div id="test1"></div> <div id="test2"></div> <div id="test3"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Person extends React.Component { render() { const { name, sex, age } = this.props return ( <ul> <li>姓名: {name}</li> <li>性别: {sex}</li> <li>年龄: {age+1}</li> </ul> ) } }
const p = {name: '张三', age: 20, sex: '男'}
ReactDOM.render(<Person name="张4" age={22} sex="女" />, document.getElementById('test2')) ReactDOM.render(<Person name="张叼毛" age={52} sex="男" />, document.getElementById('test3'))
ReactDOM.render(<Person {...p} />, document.getElementById('test1')) </script> </body>
</html>
|
对props进行限制
注意prop是不可以修改的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>2_对props进行限制</title> </head>
<body> <div id="test1"></div> <div id="test2"></div> <div id="test3"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script> <script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel"> class Person extends React.Component { render() { const { name, sex, age } = this.props return ( <ul> <li>姓名: {name}</li> <li>性别: {sex}</li> <li>年龄: {age+1}</li> </ul> ) } }
Person.propTypes = { name: PropTypes.string.isRequired, sex: PropTypes.string, age: PropTypes.number, speak: PropTypes.func, } Person.defaultProps = { sex: '男', age: 18 }
const p = {name: '张三', age: 20, sex: "男"}
ReactDOM.render(<Person name="张4" age={22} sex="女" speak={speak} />, document.getElementById('test2')) ReactDOM.render(<Person name="张叼毛" age={52} sex="男" />, document.getElementById('test3'))
ReactDOM.render(<Person {...p} />, document.getElementById('test1'))
function speak() { console.log('说话'); } </script> </body>
</html>
|
使用propTypes进行类型限制的时候, 需要在代码中引入prop-types.js
当name没有传递时
性别设置数值11
props的简写方式
将 propTypes 写入到 class 中, 使用 static 关键字, 给 class 类添加属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>3_props的简写方式</title> </head>
<body> <div id="test1"></div> <div id="test2"></div> <div id="test3"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script> <script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel"> class Person extends React.Component {
static propTypes = { name: PropTypes.string.isRequired, sex: PropTypes.string, age: PropTypes.number, speak: PropTypes.func, } static defaultProps = { sex: '男', age: 18 }
render() { const { name, sex, age } = this.props return ( <ul> <li>姓名: {name}</li> <li>性别: {sex}</li> <li>年龄: {age + 1}</li> </ul> ) } }
const p = { name: '张三', age: 20, sex: "男" }
ReactDOM.render(<Person name="张4" age={22} sex="女" speak={speak} />, document.getElementById('test2')) ReactDOM.render(<Person name="张叼毛" age={52} sex="男" />, document.getElementById('test3'))
ReactDOM.render(<Person {...p} />, document.getElementById('test1'))
function speak() { console.log('说话'); } </script> </body>
</html>
|
关于构造器中的props
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class Person extends React.Component {
constructor(props) {
super(props) console.log('constructor', this.props); }
static propTypes = { name: PropTypes.string.isRequired, sex: PropTypes.string, age: PropTypes.number, speak: PropTypes.func, } static defaultProps = { sex: '男', age: 18 }
render() { const { name, sex, age } = this.props return ( <ul> <li>姓名: {name}</li> <li>性别: {sex}</li> <li>年龄: {age + 1}</li> </ul> ) } }
|
super不传递props
this.props的输出是undefined
但是如果想使用props的话
props都传入进来了
为啥不直接使用props
类中的构造器能省略就省略, 无所叼谓
函数组件使用props
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>4_函数组件使用props</title> </head>
<body> <div id="test1"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script> <script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel"> function Person(props) { console.log(props); const {name, sex, age} = props return ( <ul> <li>姓名: {name}</li> <li>性别: {sex}</li> <li>年龄: {age + 1}</li> </ul> ) } Person.propTypes = { name: PropTypes.string.isRequired, sex: PropTypes.string, age: PropTypes.number, } Person.defaultProps = { sex: '男', age: 18 }
ReactDOM.render(<Person name="张三" age={22} sex="女" />, document.getElementById('test1')) </script> </body>
</html>
|
总结:
理解
1. 每个组件对象都会有props(properties的简写)属性
2. 组件标签的所有属性都保存在props中
作用
1. 通过标签属性从组件外向组件内传递变化的数据
2. 注意: 组件内部不要修改props数据
编码操作
1. 内部读取某个属性值
this.props.name
- 对props中的属性值进行类型限制和必要性限制
第一种方式(React v15.5 开始已弃用): 1 2 3 4 5
| Person.propTypes = { name: React.PropTypes.string.isRequired, age: React.PropTypes.number }
|
第二种方式(新):使用prop-types库进限制(需要引入prop-types库)
1 2 3 4 5 6 7 8
| Person.propTypes = { name: PropTypes.string.isRequired, age: PropTypes.number. }
```
3. 扩展属性: 将对象的所有属性通过props传递
|
<Person {…person}/>
Person.defaultProps = {
age: 18,
sex:’男’
}
constructor(props){
super(props)
console.log(props)//打印所有属性
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
|
#### refs
字符串形式的ref > 不推荐使用字符串形式的ref, 因为效率不高 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>1_字符串形式的ref</title> </head> <body> <div id="test"></div> <script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Demo extends React.Component { showData = () => { console.log(this); const {input1} = this.refs alert(input1.value) } showData2 = () => { const {input2} = this.refs alert(input2.value) }
render() { return ( <div> <input ref="input1" type="text" placeholder="点击按钮提示数据" /> <button onClick={this.showData}>点我提示左侧的数据</button> <input onBlur={this.showData2} ref="input2" type="text" placeholder="失去焦点提示数据" /> </div> ) } } ReactDOM.render(<Demo />, document.getElementById('test')) </script> </body> </html>
|
回调函数形式的ref
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>2_回调函数形式的ref</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Demo extends React.Component { showData = () => { const { input1 } = this alert(input1.value) }
showData2 = () => { const { input2 } = this alert(input2.value) }
render() { return ( <div> { /* c 表示 currentNode */} <input ref={c => this.input1 = c} type="text" placeholder="点击按钮提示数据" /> <button onClick={this.showData}>点我提示左侧的数据</button> <input onBlur={this.showData2} ref={c => this.input2 = c} type="text" placeholder="失去焦点提示数据" /> </div> ) } } ReactDOM.render(<Demo />, document.getElementById('test')) </script> </body>
</html>
|
在编写内联函数的时候, 不能随便写回调函数, 一定是要在ref中
1 2
| <input ref={(c) => {this.input1 = c; console.log('@', c);}} haha={() => {console.log('#');}} type="text" /> <br /><br />
|
回调ref中回调执行次数的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>3_回调ref中回调执行次数的问题</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Demo extends React.Component { state = {isHot: false} showInfo = () => { const {input1} = this alert(input1.value) } changeWeather = () => { const {isHot} = this.state this.setState({isHot: !isHot}) } render() { const {isHot} = this.state return ( <div> <h2>今天天气很{isHot ? '炎热' : '寒冷'}</h2> {/* 如果以 ref 使用内联函数时, 在更新过程中它会执行两次 第一次传入的参数null, 第二次传入参数DOM元素 console.log 先输出null, 然后输出当前的DOM元素 每次渲染都会创建一个新函数实例, 所以React清空旧的ref并且设置新的 通过将 ref 的回调函数定义成 class 的绑定函数的方法可以避免这种问题 大多情况下, 这是无关紧要的 */} <input ref={(c) => {this.input1 = c; console.log('@', c);}} type="text" /> <br /><br /> <button onClick={this.showInfo}>点我提示输入的数据</button> <button onClick={this.changeWeather}>点我切换天气</button> </div> ); } }
ReactDOM.render(<Demo />, document.getElementById('test')); </script> </body>
</html>
|
初始化的时候, 内联函数被调用了一次, 当按钮点击, 页面进行了更新操作, 内联函数被调用了两次,
createRef的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>4_createRef的使用</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Demo extends React.Component {
myRef = React.createRef() myRef2 = React.createRef()
showData = () => { alert(this.myRef.current.value); }
showData2 = () => { alert(this.myRef2.current.value) }
render() { return ( <div> <input ref={this.myRef} type="text" placeholder="点击按钮提示数据" /> <button onClick={this.showData}>点我提示左侧的数据</button> <input onBlur={this.showData2} ref={this.myRef2} type="text" placeholder="失去焦点提示数据" /> </div> ) } } ReactDOM.render(<Demo />, document.getElementById('test')) </script> </body>
</html>
|
总结:
理解
组件内的标签可以定义ref属性来标识自己
编码
(1).字符串形式的ref
<input ref="input1"/>
(2).回调形式的ref
<input ref={(c)=>{this.input1 = c}}/>
(3).createRef创建ref容器·
1 2
| myRef = React.createRef() <input ref={this.myRef}/>
|
事件处理
当触发事件的DOM跟回调函数在同一个的时候, 可以省略ref的用法
通过event.target的方式传递DOM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件处理</title> </head> <body> <div id="test"></div> <script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Demo extends React.Component{
myRef = React.createRef() myRef2 = React.createRef()
showData = (event)=>{ console.log(event.target); alert(this.myRef.current.value); }
showData2 = (event)=>{ alert(event.target.value); }
render(){ return( <div> <input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/> <button onClick={this.showData}>点我提示左侧的数据</button> <input onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/> </div> ) } } ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test')) </script> </body> </html>
|
react中收集表单数据
非受控组件是: 现用现取
通过按钮触发了点击事件, 获取了表单中的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>1_非受控组件</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Login extends React.Component {
handlerSubmit = (event) => { event.preventDefault(); const {username, password} = this alert(`你输入的用户名是: ${username.value}, 你输入的密码是: ${password.value}`); }
render() { return ( <form action="" onSubmit={this.handlerSubmit}> 用户名: <input ref={c => this.username = c} type="text" name="username" /> 密码: <input ref={c => this.password = c} type="password" name="password" /> <button>登录</button> </form> ) } } ReactDOM.render(<Login />, document.getElementById('test')) </script> </body>
</html>
|
受控组件相比于非受控组件区别在于, 表单中的输入DOM没有绑定一个ref
受控组件是通过state状态进行数据的关联的
onChange 中必须要将一个函数的回调交给onChange
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>2_受控组件</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Login extends React.Component {
state = { username: '', password: '' }
saveUsername = (event) => { this.setState({ username: event.target.value }) }
savePassword = () => { this.setState({ password: event.target.value }) }
handlerSubmit = (event) => { event.preventDefault(); const { username, password } = this.state alert(`你输入的用户名是: ${username}, 你输入的密码是: ${password}`); }
render() { return ( <form action="" onSubmit={this.handlerSubmit}> 用户名: <input onChange={this.saveUsername} type="text" name="username" /> 密码: <input onChange={this.savePassword} type="password" name="password" /> <button>登录</button> </form> ) } } ReactDOM.render(<Login />, document.getElementById('test')) </script> </body>
</html>
|
高阶函数_函数柯里化
对象相关的知识
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Document</title> </head> <body> <script type="text/javascript"> let a = 'name' let obj = {} obj[a] = 'tom' console.log(obj); </script> </body> </html>
|
演示函数的柯里化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Document</title> </head> <body> <script type="text/javascript">
function sum(a) { return (b) => { return (c) => { return a + b + c; } } } let result = sum(1)(2)(3) console.log(result); </script> </body> </html>
|
1_高阶函数_函数柯里化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>1_高阶函数_函数柯里化</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Login extends React.Component {
state = { username: '', password: '' }
saveFormData = (dataType) => { return () => { console.log(dataType, event.target.value); this.setState({[dataType]: event.target.value}) } }
handlerSubmit = (event) => { event.preventDefault(); const { username, password } = this.state alert(`你输入的用户名是: ${username}, 你输入的密码是: ${password}`); }
render() { return ( <form action="" onSubmit={this.handlerSubmit}> 用户名: <input onChange={this.saveFormData('username')} type="text" name="username" /> 密码: <input onChange={this.saveFormData('password')} type="password" name="password" /> <button>登录</button> </form> ) } } ReactDOM.render(<Login />, document.getElementById('test')) </script> </body>
</html>
|
2_不用函数柯里化的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>2_不用函数柯里化的实现</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Login extends React.Component {
state = { username: '', password: '' }
saveFormData = (dataType, event) => { this.setState({ [dataType]: event.target.value }) }
handlerSubmit = (event) => { event.preventDefault(); const { username, password } = this.state alert(`你输入的用户名是: ${username}, 你输入的密码是: ${password}`); }
render() { return ( <form action="" onSubmit={this.handlerSubmit}> {/* 这行代码是将this.saveFormData()函数的返回值给了onChange */ } {/* 而不是将this.saveFormDate的回调给了onChange */} 用户名: <input onChange={event => this.saveFormData('username', event)} type="text" name="username" /> 密码: <input onChange={event => this.saveFormData('password', event)} type="password" name="password" /> <button>登录</button> </form> ) } } ReactDOM.render(<Login />, document.getElementById('test')) </script> </body>
</html>
|
组件的生命周期
组件渲染到DOM的时候, 叫做挂载(组件挂载到页面上)
引出生命周期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <title>1_引出生命周期</title> </head>
<body> <div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script> <script type="text/javascript" src="../js/react-dom.development.js"></script> <script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel"> class Life extends React.Component {
state = { opacity: 1 }
death = () => { ReactDOM.unmountComponentAtNode(document.getElementById('test')) }
componentDidMount() { this.timer = setInterval(() => { console.log('#'); let { opacity } = this.state opacity -= 0.1 if (opacity <= 0) opacity = 1 this.setState({ opacity }) }, 200); }
componentWillUnmount() { clearInterval(this.timer) }
render() {
return ( <div> <h2 style={{ opacity: this.state.opacity }}>react学不会, 怎么办?</h2> <button onClick={this.death}>不活了</button> </div> ) } }
ReactDOM.render(<Life />, document.getElementById('test')) </script> </body>
</html>
|
10-7 1-10
10-8 11-20
10-10 21-29
10-11 29-
行云般流水