react-入门
1.安装脚手架工具
sudo cnpm install -g create-react-app
2.创建项目文件
create-react-app my-app
3.运行项目
npm start
npm start
npm test
npm run build
项目结构
查看当前项目的react版本 package.json中 看react的版本
查看npm发表过的react版本
npm info react
用create-react-app生成一个ts项目
npx create-react-app testts项目名 --template typescript
这样就是以ts模版的项目
生命周期
componentDidMount()
方法会在组件已经被渲染到 DOM 中后运行
构造函数是唯一可以给this.state赋值的地方
sate的更新可能是异步的,出于性能考虑,react会把多个setState合并成一个调用,所以不能依赖他们的值来更新下一个状态
需要解决这个问题,可以让setState接受一个函数而不是对象
这个函数用上一个 state 作为第一个参数,将此次更新被应用时的 props 做为第二个参数
this.setState((state, props) => ({ counter: state.counter + props.increment })); //或者 this.setState(function(state, props) { return { counter: state.counter + props.increment }; });
state 为局部的或是封装的的原因。除了拥有并设置了它的组件,其他组件都无法访问。但是可以作为props向下传递
事件处理
<form onsubmit="console.log('You clicked submit.'); return false"> <button type="submit">Submit</button> </form> function Form() { function handleSubmit(e) { e.preventDefault(); console.log('You clicked submit.'); } return ( <form onSubmit={handleSubmit}> <button type="submit">Submit</button> </form> ); }
在这里,e
是一个合成事件。React 根据 W3C 规范来定义这些合成事件,所以你不需要担心跨浏览器的兼容性问题。React 事件与原生事件不完全相同。
1.bind指定this
class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; // 为了在回调中使用 `this`,这个绑定是必不可少的 this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(prevState => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'} </button> ); } } ReactDOM.render( <Toggle />, document.getElementById('root') );
jsx回调函数的this默认不会绑定this,函数不手动绑定this会指向undefined
2.箭头函数
class LoggingButton extends React.Component { handleClick() { console.log('this is:', this); } render() { // 此语法确保 `handleClick` 内的 `this` 已被绑定。 return ( <button onClick={() => this.handleClick()}> Click me </button> ); } }
此语法问题在于每次渲染 LoggingButton
时都会创建不同的回调函数。在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题
export class 父组件 extends React.Component{ constructor(props){ super(props); this.state={ text:'文本' } } render(){ return ( <div> <LifeCycle text="{this.state.text}"></LifeCycle> </div> ) } } export class 子组件 extends React.Component{ constructor(props){ super(props); } render(){ return ( <div> <p>{this.props.text}</p> </div> ) } }
export class 父组件 extends React.Component{ constructor(props){ super(props); this.state={ text:'文本' } } //用的箭头函数 所以不需要bind this changesText=()=>{ this.setState({ text:"修改了文本" }) } render(){ return ( <div> <子组件 changesText={this.changesText}>修改内容</子组件> </div> ) } } export class 子组件 extends React.Component{ constructor(props){ super(props); this.state={ text:'文本' } } render(){ return ( <div> <button onClick={()=>{this.props.changesText()}}>修改内容</button> </div> ) } }
import React,{createContext} from 'react' //新建一个context对象 const MyContext=createContext(); const {Provider} =MyContext; class Div extends React.Component{ constructor(props){ super(props); this.state={ text:'文本' } } render(){ return ( <div> <Provider value={this.state.text}><P></P></Provider> </div> ) } } class P extends React.Component{ render(){ return ( <div> <Span></Span> </div> ) } } class Span extends React.Component{ render(){ console.log(this)//this上面就有了text return ( <div> <span>{this.context}</span> </div> ) } } //接受数据 Span.contextType=MyContext;
2.consumer 接受数据的
import React,{createContext} from 'react' //新建一个context对象 const MyContext=createContext(); const {Provider,Consumer} =MyContext; class Div extends React.Component{ constructor(props){ super(props); this.state={ text:'文本' } } render(){ return ( <div> <Provider value={this.state.text}><P></P></Provider> </div> ) } } class P extends React.Component{ render(){ return ( <div> <Consumer> {(props)=>{//Consumer接受函数,然后通过props方式传递 return (<Span text={props}></Span>) }} </Consumer> </div> ) } } class Span extends React.Component{ render(){ console.log(this)//this上面就有了text return ( <div> <span>{this.props.text}</span> </div> ) } }
react 简单实现
const createDOMFromString = (domString) => {
const div = document.createElement('div')
div.innerHTML = domString
return div
}
封装一个按钮
class LikeButton { render() { this.el = createDOMFromString(` <button class='like-button'> <span class='like-text'>点赞按钮</span> <span></span> </button> `) this.el.addEventListener('click', () => console.log('点赞了'), false) return this.el } }
React.StrictMode 是一个用来突出显示应用程序中潜在问题的工具,不用管它
const [searchTerm, setSearchTerm] = React.useState("");
useState()
采用一个初始 state 作为参数,也可以像这样使用一个空字符串。
同时它会返回包含两个值的数组,第一个值 searchTerm 表示当前 state;第二个值 setSearchTerm 是 state 的更新函数。
React fragment
这个空的 tag 就是所谓的 fragment,像这样替换掉 div 就可以让你在 HTML 树中【不留痕迹】地对事物进行分组了。
const button = (props) => ( <> <input type="button"/>, </> ); const button = (props) => ( <div> <input type="button"/>, <div/> );