【官网】 React 是一个用于构建用户界面的 JavaScript 库。
React特性
- 组件化模式,声明式编程
- 虚拟DOM+Diffing算法
- JSX语法
- 单向数据绑定
元素渲染
不要将元素与组件混淆,组件是由元素构成的。
<!-- 引入react核心库 -->
<script type="text/javascript" src="./js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="./js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="./js/babel.min.js"></script>
想要将一个 React 元素渲染到根 DOM 节点中,把它们一起传入 ReactDOM.render()
<div id="root"></div>
<script type="text/babel">
const element = <h1>React</h1>
ReactDOM.render(element, document.getElementById('root'));
</script>
jsx语法
1.标签中混入JS表达式要用 {} 。
2.样式的类名指定不要用 class,用 className 。
3.内联样式,要用 style={{ key:value }} 的形式去写。
组件
用来实现局部功能效果的代码和资源的集合。
函数组件
function Demo(props){
return <h1>一个组件</h1>;
}
ReactDOM.render(<Demo />, document.getElementById('root'));
执行 ReactDOM.render() 后,发生什么…
1.React解析组件标签,找到组件。
2.发现组件是函数定义的,随后调用函数,将返回的元素渲染。
class组件
class Demo extends React.Component {
render() {
return <h1>一个组件</h1>;
}
}
ReactDOM.render(<Demo/>, document.getElementById('root'));
执行 ReactDOM.render() 后,发生什么…
1.React解析组件标签,找到组件。
2.发现组件是类定义的,随后new出该类的实例,通过该实例调用原型上的render()方法。
3.将返回的元素渲染。
组件三大核心属性
state
state 是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
使用state【点击增加点击次数】
class Count extends React.Component {
constructor(props){
super(props)
this.state = { clickNum: 0 }
// 解决this值为undefined的问题【方法一bind】
// this.add = this.add.bind(this);
}
render() {
return (
<div>
{/* react中的事件绑定 */}
{/* 此处绑定的事件是之后作为回调函数直接调用的,调用时会没有实例的this */}
<button onClick={this.add}>点一下</button>
<h1>你点击了{this.state.clickNum}次</h1>
</div>
)
}
// 解决this值为undefined的问题【方法二箭头函数】
add = ()=>{
this.setState({clickNum:this.state.clickNum+1})
}
}
// 简化代码
class Count extends React.Component {
state = { clickNum: 0 }
render() {
return (
<div>
<button onClick={this.add}>点一下</button>
<h1>你点击了{this.state.clickNum}次</h1>
</div>
)
}
add=()=>{
this.setState({clickNum:this.state.clickNum+1})
}
}
1.不能直接修改 state,要通过 setState 修改
2.解决 this 值为 undefined 的两种方法
props
每个组件对象都会有 props 属性,组件标签的所有属性都保存在 props 中。
使用props【展示人的信息】
class Person extends React.Component {
render() {
const {name,sex,age} = this.props
return (
<div>
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
</div>
)
}
}
ReactDOM.render(<Person name="xiaohua" sex="女" age="18"/>, document.getElementById('root'));
// 批量传递props
const p = {name:"xiaohua",sex:"女",age:"18"}
ReactDOM.render(<Person {...p}/>, document.getElementById('root'));
1.批量传递props。
2.props是只读的。
refs
组件内的标签可以定义 ref 属性来标识自己
使用refs【点击获取输入框数据】
- 字符串形式
class Intext extends React.Component {
showData = ()=>{
const {txt} = this.refs
alert(txt.value)
}
render() {
return (
<div>
<input ref="txt" type="text" placeholder="请输入"></input>
<br/><br/>
<button onClick={this.showData}>点击提示数据</button>
</div>
)
}
}
- 回调形式
要知道在这里写的这个函数是一个回调函数
这个过程会把 ref 当前所在的节点挂在实例身上并命名为 txt,然后就可以从实例上获取数据
class Intext extends React.Component {
showData = ()=>{
const {txt} = this
alert(txt.value)
}
render() {
return (
<div>
<input ref={currentNode => this.txt=currentNode} type="text" placeholder="请输入"></input>
<br/><br/>
<button onClick={this.showData}>点击提示数据</button>
</div>
)
}
}
- createRef
createRef 调用后可以返回一个容器,该容器可以存储被 ref 所标识的节点
一个容器只能存一个
class Intext extends React.Component {
myRef = React.createRef()
showData = ()=>{
alert(this.myRef.current.value)
}
render() {
return (
<div>
<input ref={this.myRef} type="text" placeholder="请输入"></input>
<br/><br/>
<button onClick={this.showData}>点击提示数据</button>
</div>
)
}
}
1.不要过度使用 ref
2.通过 event.target 可以得到发生事件的DOM元素对象
表单
非受控组件
随着输入维护状态
class Login extends React.Component {
state={
username:'',
password:''
}
// 保存用户名到状态中
saveUsername = (event)=>{
this.setState({username:event.target.value})
}
// 保存密码到状态中
savePassword = (event)=>{
this.setState({password:event.target.value})
}
// 表单提交的回调
handleSubmit = (event)=>{
event.preventDefault() // 阻止表单提交
const {username, password} = this.state
console.log(`用户名:${username}密码:${password}`)
}
render() {
return (
<form onSubmit={this.handleSubmit}>
用户名:<input onChange={this.saveUsername} type="text" name="username" />
<br/><br/>
密码:<input onChange={this.savePassword} type="password" name="password"/>
<br/><br/>
<button>登录</button>
</form>
)
}
}
合并一下保存值到状态的函数【用函数柯里化】
函数柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。
class Login extends React.Component {
// 保存表单数据到状态中
saveFormData = (dataType)=>{
return (event)=>{
this.setState({[dataType]:event.target.value})
}
}
// 表单提交的回调
handleSubmit = (event)=>{
event.preventDefault() // 阻止表单提交
const {username, password} = this.state
console.log(`用户名:${username}密码:${password}`)
}
render() {
return (
<form onSubmit={this.handleSubmit}>
用户名:<input onChange={this.saveFormData('username')} type="text" name="username" />
<br/><br/>
密码:<input onChange={this.saveFormData('password')} type="password" name="password"/>
<br/><br/>
<button>登录</button>
</form>
)
}
}
受控组件
现用现取
class Login extends React.Component {
// 表单提交的回调
handleSubmit = (event)=>{
event.preventDefault() // 阻止表单提交
const {username, password} = this
console.log(`用户名:${username.value}密码:${password.value}`)
}
render() {
return (
<form onSubmit={this.handleSubmit}>
用户名:<input ref={c =>this.username=c} type="text" name="username" />
<br/><br/>
密码:<input ref={c => this.password=c} type="password" name="password"/>
<br/><br/>
<button>登录</button>
</form>
)
}
}