一、react框架入门
1.介绍
react 是facebook开源的库,用于构建用户界面的 JavaScript 库,它不是一个完整的MVC,最多可以认为是MVC中的V(view视图层)。
官网:https://react.docschina.org/
优势:
浏览器兼容性好
一切皆组件
虚拟DOM(diff)
JSX语法糖
缺点:
不是一个完整的MVC设计模式,自己本身无法开发大型项目,需要结合flux、redux。
2.基本使用
第一步:引入核心库
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
第二步:设置一个容器
<div id="app"></div>
第三步:创建虚拟DOM,并渲染到页面上
ReactDOM.render(React.createElement('h1',{},"这是一个h1标题"),document.getElementById('app'))
3.JSX语法糖【可选,推荐使用】
使用createElement方法可以创建出来虚拟DOM,但是如果虚拟DOM的结构和层级比较复杂时,再使用createElement方法就会很吃力了,所以facebook专门为React开发了一套JSX语法糖。
JSX语法糖是facebook专门为react开发的一套语法糖,它不是一个新的语法,而是将之前的js、html进行整合,方便程序开发人员更好的开发和阅读代码。
JSX允许JavaScript和HTML混合在一起使用。
特点:遇到<时就解析成HTML语法,遇到{时就解析成JS语法。
第一步:引入解析JSX语法的核心库
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
第二步:修改script的type属性
<script type="text/babel">
script的type属性默认为text/javascript,浏览器会识别script中的写的脚本代码为js
第三步:创建虚拟DOM并渲染到页面中
var el = <div>
<p>jsx语法糖的使用</p>
<span></span>
</div>
ReactDOM.render(el,document.getElementById('app'))
4.数据类型解析
<script type="text/babel">
// 字符串
var str = 'hello react';
// 数字
var num = 145
// 布尔值 在react中,布尔值不能直接渲染,可以进行条件判断
var islogin = false;
// 对象 在react中,对象类型数据不能直接渲染,可以渲染对象中的某个属性
var obj = {
name:'小飞',
age:20
}
// 数组 在react中,数组元素如果是对象的话,也不能把对象渲染到页面上
var arr = [{title:'标题',price:200}]
var el = (
<div>
<h1>{ str }</h1>
<p>{ '数量:' + (num+10) }</p>
<p>{ islogin ? '已登录' : '未登录' }</p>
<p>{ obj.name }</p>
<p>{ arr }</p>
</div>
);
var box = document.getElementById('box')
ReactDOM.render(el,box);
</script>
5.属性绑定
className
style
<li className="red" key={index} style={{ fontSize:26 }}
在style中
第一个花括号解析成js语法,第二个花括号表示是一个对象
像素单位默认是px,可以不用写,如果是其他单位,需要进行拼接
img
var imgurl = '图片地址'
<img src={ imgurl } />
二、常见错误
1.babel.min.js:7 Uncaught SyntaxError: Inline Babel script: Adjacent JSX elements must be wrapped in an enclosing tag (5:57)
虚拟DOM只能有一个根标签
2.Warning: Invalid DOM property class
. Did you mean className
?
in div
在react中,class是类的关键词,所以不能用class属性,要使用className
3.Uncaught SyntaxError: Inline Babel script: Unterminated JSX contents
在jsx中,所有的标签都要有闭合,包括单闭合标签
input、img、br、hr
4.Warning: Invalid DOM property for
. Did you mean htmlFor
?
在react中,for是遍历循环的关键词,label标签不能用for属性,需要改成htmlFor
5.Warning: Each child in a list should have a unique “key” prop.
在遍历循环生成虚拟DOM时,需要给虚拟DOM设置一个key属性来唯一标识这个DOM结构,加快渲染速度。
6.react-dom.development.js:6824 Uncaught Error: The style
prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + ‘em’}} when using JSX.
在react的jsx语法中,style预期得到的是一个对象,而不是字符串
7.Warning: The tag is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
react的组件名要首字母大写
三、脚手架
1.安装
npm i create-react-app -g
2.初始化项目
进入一个指定的目录(不建议在桌面)
create-react-app 项目名称
3.运行项目
进入项目根目录,然后执行命令
npm start
4.项目目录结构
项目名称
node_modules 项目依赖目录
public 项目运行根目录
index.html 项目运行首页
src 项目源码目录
index.js 项目启动文件
index.css 项目全局样式文件
App.js 项目根组件
App.css 项目根组件样式
5.项目运行流程
/public/index.html
/src/index.js
/src/App.js
四、组件
1.函数式组件
它没有自己的业务逻辑,无状态组件(木偶组件)
(1)es5方式
var Home = function(){
return(
<div>
<h1>home页面</h1>
</div>
)
}
export default Home;
(2)es6
export default ()=>{
return(
<div>
<h1>home页面</h1>
</div>
)
}
2.类组件
状态组件(业务组件),类组件有生命周期。
示例代码:
方式一:
import React from 'react'
class Order extends React.Component{
constructor(){
super();
console.log('构造函数先执行')
// console.log(this)
}
render(){
console.log('render函数执行了')
return(
<div>
<h1>这是order页面</h1>
</div>
)
}
}
export default Order;
方式二:
import React,{ Component } from 'react'
export default class Order extends Component{
render(){
return(
<div>
<h1>这是order页面</h1>
</div>
)
}
}
五、事件
1.事件绑定
(1)es5方式
在给按钮绑定点击事件时,不需要传递参数的时候,不要写小括号,否则指定的函数会自动执行。
import React,{ Component } from 'react'
export default class Index extends Component{
render(){
return(
<div>
<h1>index页面-事件</h1>
{/* 事件绑定-es5方式 */}
<button onClick={ this.addnum }>点击</button>
</div>
)
}
addnum(){
console.log('addnum....')
console.log(this)
}
}
此时,在绑定的函数中,无法获取this,如果想要在自定义函数中获取this,需要bind进行绑定
<button onClick={ this.addnum.bind(this) }>点击-es5-有this</button>
(2)es6方式
<button onClick={ ()=>this.handler1() }>点击-es6</button>
箭头函数,可以保持this指向
2.事件对象
(1)es5方式
<button onClick={ this.handler2 }>事件对象-es5</button>
在es5方式中,事件触发函数时,不传递参数,在对应的事件函数中有形参的话,这个形参就是事件对象。
(2)es6方式
<button onClick={ (e)=>this.handler2(e) }>事件对象-es6</button>
es6语法中,如果不主动传递事件对象,那么在自定义函数中是无法获取到事件对象的。
3.传参
(1)es5方式
在es5方式中,需要传递额外参数时,要使用bind(this,实参1)
在函数定义中的第一个形参就是传递的实参,(形参就不再是事件对象了)
如果还想获取事件对象,那么需要在函数定义中多添加一个形参(最后一个),它就是事件对象
<button onClick={ this.handler3.bind(this,'hello',100) }>传递参数-es5</button>
js代码
handler3(e,str,ev){
console.log(e,111111)
console.log(str,22222)//前两个参数是传递的实参
console.log(ev)//ev是事件对象
// console.log(this)
}
(2)es6方式
<button onClick={ (e)=>this.handler3(e,'测试',555) }>传递参数-es6</button>
es6使用箭头函数调用自定义函数时,实参传递的是什么内容,形参接收到的就是什么。
六、状态机
每一个类组件中,都有一个state属性,我们可以把页面组件的初始数据放到state中。
当页面中需要修改初始数据并让页面重新渲染,需要使用setState函数来执行
setState完成了两件事情:
第一个是把指定数据与原来state中的数据进行合并
第二个是调用diff算法进行页面的重新渲染。
import React, { Component } from 'react'
export default class Order extends Component {
constructor(){
super();
this.state = { num:100 }
}
add(){
// this.state.num++;
// this.render();//这种方法会修改数据,但是页面不会变化
var num = this.state.num;//react中不能直接对state进行修改,所以先取出原有的值,然后再进行修改
this.setState({
num:++num
})
}
render() {
console.log('页面渲染了....')
return (
<div>
<h1>order页面</h1>
<p>订单数量为:{ this.state.num }</p>
<button onClick={ ()=>this.add() }>点击增加</button>
</div>
)
}
}
七、模拟表单元素双向绑定
import React, { Component } from 'react'
export default class Form extends Component {
state = {
username:'',
phone:''
}
iptChange(e){
// console.log(e.target)
// this.setState({
// username:e.target.value
// })
var data = this.state;
data[e.target.id] = e.target.value;
this.setState(data)
}
submit(){
console.log(this.state)
}
render() {
return (
<div>
<h1>表单信息收集</h1>
用户名:<input type="text" id="username" value={ this.state.username } onChange={ (e)=>this.iptChange(e) }/>
<p>{ this.state.username }</p>
<br/>
手机号:<input type="text" id="phone" value={ this.state.phone } onChange={ (e)=>this.iptChange(e)}/>
<p>{ this.state.phone }</p>
<br/>
<button onClick={ ()=>this.submit() }>提交</button>
</div>
)
}
}