# react 开发JS
react.development.js
# react dom渲染JS
react-dom.development.js
# jsx语法转换JS
babel.min.js
# 参数传值校验JS
prop-types.js
# 容器
<div id="test"></div>
# 注意写JSX语法需要定义为babel
<script type="text/babel">
const myName = "flower";
# 创建虚拟DOM, 不需要写双引号 换行使用()包裹
const vdom = (
# 最外侧只能包裹一个标签 建议使用div
<div>
# 变量取值使用{}, style样式使用{{中间使用逗号隔开}}
<h1 style={{color:'yellow'}}>{myName}</h1>
# 声明class属性使用className
<h2 className="title"></h2>
</div>
)
# 渲染到页面 传入虚拟DOM或者组件, 容器
ReactDOM.render(vdom,document.getElementById("test"))
</script>
function Demo(){
# 直接返回虚拟DOM
return <h1>函数式组件2</h1>
}
# 首字母大写 并 继承 React.Component
class Demo extends React.Component {
# state 状态管理
state = {
# 需要使用的变量 建议直接在state中声明好
isHot: true
}
# 渲染函数返回虚拟DOM
render(){
const { isHot } = this.state;
return (
<h1 onClick={this.modifyWater}>今天天气很{isHot?"炎热":"寒冷"}</h1>
)
}
// 只能写箭头函数, 不然this指针就需要在构造方法中绑定this
modifyWater = () => {
// 不能直接修改对象, 需要调用setState, 传入对象修改值, 修改不是替换对象,而是对比赋值
this.setState({isHot:!this.state.isHot})
}
}
# 开头大写就是组件, 小写就是html标签
ReactDOM.render(<Demo />,document.getElementById("test"))
class Person extends React.Component {
// 参数校验 必须写static
static propTypes = {
// 字符串必填
name: PropTypes.string.isRequired,
sex: PropTypes.string,
// 数字
age: PropTypes.number,
// 函数
speck: PropTypes.func
}
# 设置默认值
static defaultProps = {
sex: "无"
}
render() {
# 从props取值
const {name, age, sex} = this.props;
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
let personInfo = {
name:"flower",
sex: "男",
age: 18
}
# 结构传值
# 相当于 name={personInfo.name} sex=.....
ReactDOM.render(<Person {...personInfo}/>, document.getElementById("test"))
# 定义方式一 : 字符串 : 不建议
<input ref="leftInput" type="text" placeholder="点击按钮显示数据"/>
# 获取方式, 获取到的是真实DOM节点
const leftInput = this.refs.leftInput
# 定义方式二 : 函数 : 建议[建议使用引用函数, 不然会每次渲染都重新赋值一遍,但是官方说没啥事]
<input ref={ val => this.val=val} type="text" />
# 获取方式
const val = this.val
# 定义方式三 : React.createRef() : 推荐
# 我对这种方式进行了优化
# 调用函数
<input ref={this.refsiCopy('inputOne')} type="text" onBlur={this.blur} placeholder="失去焦点显示数据"/>
# 存储容器
refsi = {}
# 函数赋值
refsiCopy = nodeName => {
return this.refsi[nodeName] = React.createRef()
}
# 使用, 从自定义存储容器中获取
blur = () => {
console.log(this.refsi);
const {value} = this.refsi['inputOne'].current;
alert(value)
}
class Demo extends React.Component {
render() {
return (
<div>
# 定义事件, 通过驼峰定义, React在原生事件上,包装了一层, 默认会传入event对象
<input type="text" onBlur={this.blur} placeholder="失去焦点显示数据"/>
</div>
)
}
// 获取事件 入参event
blur = (event) => {
console.log(event.target);
# 获取值
console.log(event.target.value)
}
}
# 非受控组件 值直接挂在对象上, 而不是state, 所以是非受控组件
class Demo extends React.Component {
render() {
return (
<div>
# 表单提交
<form onSubmit={this.handlerSubmit}>
# 函数ref
用户名:<input ref={c => this.username = c} name="username" type="text"/>
密码:<input ref={c => this.password = c} name="password" type="password"/>
<button>登录</button>
</form>
</div>
)
}
# 执行表单
handlerSubmit = (event) => {
// 阻止表单默认事件
event.preventDefault();
const {username,password} = this;
console.log(username.value,password.value)
}
}
# 受控组件, 使用state控制值
class NameForm extends React.Component {
state = {
value:'123'
}
handleChange = (event) => {
# 通过setState修改值
this.setState({value: event.target.value});
}
handleSubmit = (event) =>{
# 获取state中的值
alert('提交的名字: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
名字:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="提交" />
</form>
);
}
}
class NameForm extends React.Component {
state = {
input: '123'
}
// 返回一个函数给onChange 然后让React传入event 解决传递参数的问题
handleChange = (input) => {
# 返回函数, 用于React调用,传入event对象
return event => {
this.setState({[input]: event.target.value})
}
}
render() {
return (
<label>
# 因为事件必须赋值一个函数, 但是直接加(),会被渲染的时候直接就执行掉,返回的是值/undefined, 所以需要在执行函数中, 返回一个函数, 来给React调用
名字:<input type="text" onChange={this.handleChange('input')}/>
<span>{this.state.input}</span>
</label>
);
}
}
class Demo extends React.Component {
// 会在组件挂载后(插入 DOM 树中)立即调用。
// 依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。
componentDidMount() {
// 启动定时器
this.action()
}
// 将要卸载的时候执行
componentWillUnmount(){
// 取消定时器
clearInterval(this.state.active)
}
state = {
opacity: 1,
active: undefined
}
action = () => {
const active = setInterval(() => {
console.log("1")
let {opacity} = this.state
opacity -= 0.1
if (opacity <= 0) opacity = 1
this.setState({opacity})
}, 200)
this.setState({active})
}
remove = () => {
// 卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById("test"))
}
render() {
return (
<div>
<h2 style={{opacity: this.state.opacity}}>React好难呀</h2>
<button onClick={this.remove}>不学了</button>
</div>
)
}
}
16.3
>=16.4
其实其他生命周期的基本不用, 用的话也可以通过别的方式实现
常用的生命周期就三个
生命周期 | 作用 |
---|---|
render | 渲染DOM |
componentDidMount | 挂载完组件后,一般用于加载网络请求初始化数据 |
componentWillUnmount | 组件将要卸载, 做一些处理关闭的操作, 比如关闭定时器啥的 |