react
一、react介绍
- react是用于构建用户界面的JavaScript库,是一个将数据渲染为HTML视图的开源JavaScript库。
- react特点:采用组件化模式、声明式编码、提高开发效率及组件复用率;在React Native中可以使用React语法进行移动端开发;使用虚拟DOM+优秀Diffing算法,尽量减少与真实DOM进行交互。
- react库:babel.min.js:将jsx转换为js;react.development.js:react核心库;react-dom.development.js:react扩展库。
二、hello react
<!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>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
<div id="div1"></div>
<script type="text/babel">
const VDOM=<h1>hello react</h1>
ReactDOM.render(VDOM,document.getElementById('div1'))
</script>
</body>
</html>
- react里使用的是jsx。jsx即JavaScript XML,是一种在React组件内部构建标签的类XML语法,使用babel.min.js库会将jsx转化为js。
- 虚拟DOM的两种创建方式:使用jsx或使用js来创建虚拟DOM,jsx创建虚拟DOM是使用原生JS创建虚拟DOM的语法糖,在实际使用中不会使用js来创建虚拟DOM,因为在创建一些复杂嵌套标签时太过复杂。
<div id="div1"></div>
<script type="text/javascript">
const VDOM=React.createElement('h1',{id:'title'},'hello react')
ReactDOM.render(VDOM,document.getElementById('div1'))
</script>
- 虚拟DOM本质上是Object类型的对象;虚拟DOM含属性少,真实DOM含属性多,因为虚拟DOM是react内部在用,无需真实DOM上那么多的属性;虚拟DOM最终会被react转化为真实DOM,呈现在页面上。
三、jsx语法规则
- JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。XML:XML是可扩展标记语言,早起用于存储和数据传输(后面就用JSON了)。
- 语法:
- 定义虚拟DOM时,不要写引号;
- 标签中使用JS表达式时要用{};
- 样式的类名指定不要用class,要用className;
- 内联样式要使用style={{key:value}}的形式去写;虚拟DOM只能有一个根标签且标签必须闭合;
- 标签首字母:若以小写字母开头,则将该标签转化为html中同名元素,若html中无该标签同名元素,则会报错;若以大写字母开头,react就会渲染对应的组件,若组件没有定义,则报错。
const myID = 'A'
const myData = 'HELLO REACT'
const VDOM = (
<div>
<h2 id="{myID}" className="title">
<span style={{ color: 'green', }}>{myData}</span>
</h2>
<input type="text"></input>
</div>
)
- 注意区分js表达式和js语句。js表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方。
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('div1'))
四、模块与组件
- 模块:一般一个js文件就是一个模块,它向外提供特定的功能。拆分模块降低了代码的耦合性,提高了js的运行效率。当应用都以模块来编写,这个应用就是一个模块化的应用。
- 组件:用来实现局部功能效果的代码和资源的集合。使用组件复用编码,简化项目编码,提高运行效率。当应用以多组件的方式实现,这个应用就是一个组件化应用。
五、React面向组件编程
- 定义组件—函数式组件:(注意:函数名必须大写且函数必须有返回值,渲染组件到页面时必须写组件标签)
<script type="text/babel">
function MyComponent(){
console.log(this)
return <h2>函数定义组件</h2>
}
ReactDOM.render(<MyComponent/>,document.getElementById('div1'))
</script>
- react执行上面代码流程:react解析组件标签,找到了MyComponent组件,发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面上。
- 组件里的this值是undefined,这是因为代码首先会经过babel的翻译,之后会开启严格模式(ES5),他会禁止自定义函数的this指向window,所以是undefined。
- 在Chrome上安装React Developer Tools工具,然后可以在Components中查看组件相关信息,props是组件上的一些属性,rendered by表示当前页面是由哪个版本的react渲染的。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/0392b74c5c1cd67404e728693aabf8d7.png#pic_center)
- 复习类的使用:类中的构造器不是必须写的,要对实例进行一些初始化时如添加指定属性时才写;如果A类继承了B类,且A中使用了构造器,那么A类构造器中的super是必须要调用的;类中所定义的方法,都是放在类的原型对象上,供实例对象使用。
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
}
speak(){
console.log(`我的名字是${this.name},我的年龄是${this.age},我的成绩是${this.grade}`)
}
study(){
console.log('好好学习天天向上')
}
}
const p1=new Person('alice',18)
const p2=new Person('bob',19)
console.log(p1)
console.log(p2)
p1.speak();
p2.speak();
- 定义组件—类式组件:
class MyComponent extends React.Component{
render(){
return <h2>类式组件(适用于复杂组件)</h2>
}
}
ReactDOM.render(<MyComponent/>,document.getElementById('div1'))
- react执行上面代码流程:react解析组件标签,找到了MyComponent组件,发现组件是使用类定义的,随后创建出该类的实例,并通过该实例调用到原型上的render方法,将返回的虚拟DOM转换为真实DOM,随后呈现在页面上。
六、组件实例的三大属性—1. state
- 简单组件和复杂组件的最大区别是复杂组件有状态,而简单组件没有状态。
- state是组件对象最重要的属性,state的值是对象,可以包含多个key-value的组合;组件被称为状态机,通过更新组件的state来更新对应的页面显示(重新渲染页面)。
- 注意:1.组件中render方法中的this为组件实例对象;2.组件自定义的方法中this为undefined,解决这个问题需要使用赋值语句加箭头函数的方式定义方法,或者通过函数对象的bind()来强制绑定this;3.状态数据不能直接更新或修改,需要使用setState()来修改。
<div id="div1"></div>
<script type="text/babel">
class MyComponent extends React.Component{
state={isHot:true,wind:'微风'}
render(){
console.log(this)
const {isHot}=this.state
return <div onClick={this.changeWeather}><h2>今天天气很{isHot?'炎热':'凉爽'}</h2></div>
}
changeWeather=()=>{
const isHot=this.state.isHot
this.setState({isHot:!isHot})
}
}
ReactDOM.render(<MyComponent/>, document.getElementById('div1'))
</script>
七、组件实例的三大属性—2. props
- 每个组件对象都会有props属性,组件标签的所有属性都保存在props中。作用是通过标签属性从组件外向组件内传递变化的数据,但是组件内部不修改props数据,因为props数据是只读数据。
- 构造器:在react中,构造器仅用于以下两种情况,通过给this.state赋值对象来初始化内部state;为事件处理函数绑定实例。构造器是否接收props是否传递给super,取决于是否希望在构造器中通过this访问props。类中的构造器能省略就省略。
<div id="div1"></div>
<script type="text/babel">
class Person extends React.Component {
constructor(props){
super(props)
}
render() {
const { name, gender, age } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{gender}</li>
<li>年龄:{age}</li>
</ul>
)
}
static propTypes = {
name: PropTypes.string.isRequired,
gender: PropTypes.string,
age: PropTypes.number,
}
static defaultProps = {
gender: '男',
age: 18,
}
}
let person = { name: 'alice', gender: '女', age: 18 }
ReactDOM.render(<Person {...person} />, document.getElementById('div1'))
</script>
八、组件实例的三大属性—3. refs
- 字符串形式ref
<div id="div1"></div>
<script type="text/babel">
class Demo extends React.Component {
render() {
return (
<div>
<div>
<input ref='input1' type="text" placeholder='点击按钮提示数据' />
<button onClick={this.showData}>按钮</button>
</div>
<div><input onBlur={this.showData2} ref='input2' type="text" placeholder='失去焦点提示数据' /></div>
</div>
)
}
showData=()=>{
const {input1}=this.refs
alert(input1.value)
}
showData2=()=>{
const {input2}=this.refs
alert(input2.value)
}
}
ReactDOM.render(<Demo/>,document.getElementById('div1'))
</script>
- 回调refs:如果回调函数refs是以内联的方式定义的,在更新的过程中会被执行两次,第一次传入参数是null,然后第二次会传入参数DOM元素。这是因为在每次渲染时会创建一个新的函数实例,所以react清空旧的ref并设置新的。通过将ref的回调函数定义为class的绑定函数的方式可以避免上述问题。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c8deaf88758e9540f71ef08481c9bd03.png#pic_center)
- createRef:React.createRef调用后返回一个容器,该容器可以存储被ref所标识的节点,该容器专人专用。
<div id="div1"></div>
<script type="text/babel">
class Demo extends React.Component {
myRef1=React.createRef()
myRef2=React.createRef()
render() {
return (
<div>
<div>
<input ref={this.myRef1} type="text" placeholder='点击按钮提示数据' />
<button onClick={this.showData}>按钮</button>
</div>
<div><input onBlur={this.showData2} ref={this.myRef2} type="text" placeholder='失去焦点提示数据' /></div>
</div>
)
}
showData=()=>{
alert(this.myRef1.current.value)
}
showData2=()=>{
alert(this.myRef2.current.value)
}
}
ReactDOM.render(<Demo/>,document.getElementById('div1'))
</script>