React入门笔记

第一章  react基本使用

react基础首先不使用脚手架工具,只学习相关语法

Hello World输出

因为react是通过创建虚拟DOM,然后把虚拟DOM添加到DOM树中,以此达到控制视图的目的,所以首先使用react的时候需要先引入react相关文件和babel(把jsx转换成js)。

<!-- 容器 -->
    <div id="text"></div>
    
    <!-- 一定要带上babel,告诉编译器里面写的语法需要转换 -->
    <script type="text/babel">
        //创建 一个虚拟DOM
        const VDOM = <h1>Hello World</h1>
        //将虚拟DOM添加到DOM树上
        ReactDOM.render(VDOM,document.getElementById('text'));
    </script>

使用js创建 虚拟DOM

可以看到,要想使用jsx创建虚拟dom,需要引入babel文件,通过babel文件,将jsx转换成js,以此被编译器识别,事实上利用react文件,可以不使用jsx,直接创建 虚拟dom

<!-- 容器 -->
    <div id="text"></div>
    
    
    <script type="text/javascript">
        //创建 一个虚拟DOM
        const VDOM = React.createElement('h1',{id:'title'},'Hello React')
        //将虚拟DOM添加到DOM树上
        ReactDOM.render(VDOM,document.getElementById('text'));
    </script>

可以看到,用js创建虚拟dom要比用jsx麻烦的多,因此在日常的react学习中,通常 使用jsx来创建虚拟DOM

jsx语法规则

 <script type="text/babel">
        //创建 一个虚拟DOM
        let text = "Hello world"
        //根标签为h1
        const VDOM = <h1 className = "wrap"><span style={{fontSize:30}}>{text}</span></h1>
        //将虚拟DOM添加到DOM树上
        ReactDOM.render(VDOM,document.getElementById('text'));
    </script>
  • 定义虚拟dom就行写标签一样,不需要在外面在引号包裹
  • 标签中混入js表达式时要用{}包裹
  • 样式的类名不要用class,而应该用className
  • 内联样式要用{{}}包裹,外面一层{}表示jsx语法要用{}包裹,里面的{}指一个样式对象
  • 只有一个根标签,其余标签要包裹在根标签中
  • 标签闭合
  • 标签小写表示html自带标签,标签大写表示为自定义的react组件

jsx练习

因为jsx里面可以使用js表达式,因此可以在{}渲染数据

 <!-- 容器 -->
    <div id="text"></div>
    
    <!-- 一定要带上babel,告诉编译器里面写的语法需要转换 -->
    <script type="text/babel">
        let text = ['VUE','REACT','ANGULAR']
        //创建 一个虚拟DOM
        const VDOM = <h1><ul>{text.map((item,index)=>{
            return <li key={index}>{item}</li>
        })}</ul></h1>
        //将虚拟DOM添加到DOM树上
        ReactDOM.render(VDOM,document.getElementById('text'));
    </script>

函数式组件

组件可以被复用,把相同功能的模块封装成一个组件,那么就可以按需调用,节省时间和效率

<script type="text/babel">
        //创建函数式组件
        function Mycomponent(){
            return <h1>Hello React</h1>
        }
        //将虚拟DOM添加到DOM树上
        ReactDOM.render(<Mycomponent/>,document.getElementById('text'));
    </script>

类的复习

https://blog.csdn.net/wenyeqv/article/details/113180003

类式组件

  class Mycomponent extends React.Component {
            render() {
                return <h1>Hello World</h1>
            }
        }
        ReactDOM.render(<Mycomponent/>,document.getElementById('text'))

第二章 组件核心属性

1.state

state存储状态

state是组件从React中继承的属性,用来存放组件状态

class Mycomponent extends React.Component {
            constructor(props){
                super(props);
                this.state = {
                    isHot:true
                }
            }
            render(){
                return (
                    <h1>今天的天气很{this.state.isHot?"炎热":"凉爽"}</h1>
                )
            }
        }
        //将虚拟DOM添加到DOM树上
        ReactDOM.render(<Mycomponent/>,document.getElementById('text'));

state中的this指针问题

还是 上面的案例,如果想要修改state,首先需要获取到state,然后修改它的值,而state在Mycomponent实例中,用this获得,这里就需要时刻注意,每次使用的this,究竟是指什么

 class Mycomponent extends React.Component {
            constructor(props){
                super(props);
                this.state = {
                    isHot:true
                }
            }
            changeW(){
                console.log(this)
            }
            render(){
                return (
                    <h1 onClick={changeW}>今天的天气很{this.state.isHot?"炎热":"凉爽"}</h1>
                )
            }
        }
        //将虚拟DOM添加到DOM树上
        ReactDOM.render(<Mycomponent/>,document.getElementById('text'));

这里在类中创建一个方法,用来输出this,但是运行会报错,提示找不到changeW,原因是类中的函数将会被放在原型上,用来被类的实例来调用,如果直接写成onClick = { changeW },将会变成直接调用,此时全局没有changeW函数,所以会报错,因此render方法和constructor方法中的this都指向类的实例,所以改成onClick = { this.changeW } ,即可变成实例调用changeW,那么就可以在原型上找到这个函数了。

虽然这个函数可以调用了,但是输出的this却是undefine,这又是为什么呢?

原因很简单,还是那句话,只有类的实例调用类的函数,函数的this才指向类的实例,而这里的this肯定不是类的实例在调用。

我们可以用一个简单的例子来验证

  class Mycomponent extends React.Component {
            constructor(props){
                super(props);
                this.state = {
                    isHot:true
                }
            }
            changeW(){
                console.log(this)
            }
            render(){
                return (
                    <h1 onClick={this.changeW}>今天的天气很{this.state.isHot?"炎热":"凉爽"}</h1>
                )
            }
        }
        //将虚拟DOM添加到DOM树上
        ReactDOM.render(<Mycomponent/>,document.getElementById('text'));

        let m1 = new Mycomponent();
        m1.changeW();
        let x = m1.changeW;
        x();

我们自己来创建Mycomponent的实例 m1,用m1调用changeW,可以成功输出Mycomponent实例,而用x调用,却显示undefine

 

这就是关键所在

当实例调用类中的函数时,函数中的this指向实例,但是如果在全局声明一个x,将类中的函数的地址赋值给x,然后通过x()的方式 就可以调用类中的函数,这时已经不是通过实例在调用了,而是在全局调用,全局调用应该返回window,而此时又是在babel环境下,其严格遵守严格模式,严格模式下,全局的this为undefine

所以回到原来的代码中 onClick = { this.changeW},这里只是把changeW的地址给了onCLick事件,当onClick事件调用changeW的时候,已经不是实例调用changeW了

要想解决这个问题也很简单,其中一条思路就是利用bind()

 constructor(props){
                super(props);
                this.changeW = this.changeW.bind(this)
                this.state = {
                    isHot:true
                }
            }
            changeW(){
                console.log(this)
            }

在构造器中,实现这样一行代码:this.changeW = this.changeW.bind(this)

首先看等式右边,this.changeW肯定是在原型链上找到了changeW方法,然后bind(),bind()实现两件事:

  • 返回一个函数
  • 让函数的指向指向bind()传进去的参数

这里bind()传进去了this,所以整个右边的语句就是返回一个函数,函数的指向为constructor,也就是实例

而左边呢,左边则声明了一个属性,用来接受右边返回的函数。

这样,实例中有了一个changeW属性,实例原型上有了一个changeW方法,而在类组件中,跟具原型链查找规则,肯定是先使用changeW属性,所以最后组件执行的其实是实例的属性,这个属性指向一个方法,这个方法里面的指向为实例。

可以 通过这个方法验证:

   class Mycomponent extends React.Component {
            constructor(props){
                super(props);
                this.text = this.changeW.bind(this)
                this.state = {
                    isHot:true
                }
            }
            changeW(){
                console.log(this)
            }
            render(){
                return (
                    <h1 onClick={this.text}>今天的天气很{this.state.isHot?"炎热":"凉爽"}</h1>
                )
            }
        }
        //将虚拟DOM添加到DOM树上
        ReactDOM.render(<Mycomponent/>,document.getElementById('text'));

改成this.text = this.changeW.bind(this),组件中调用this.text,结果不变

state简写形式

  • 因为state属性继承自父类,说明实例中已经有state,只不过是null,所以可以直接赋值
  • 自定义的函数几乎全部为回调,不可能通过类的实例进行调用,因为React中只有组件,类的实例过程被隐藏,所以要通过bind()方法,这里可以改成回调函数。
 class Mycomponent extends React.Component{
            state = {
                isHot : true
            }
            changeW = () =>{
              let  {isHot} = this.state
              isHot = !isHot
                this.setState({
                    isHot:isHot
                })
            }
            render(){
                return(
                    <h1 onClick = {this.changeW}>今天天气很{this.state.isHot?"炎热":"凉爽"}</h1>
                )
            }
        }
        ReactDOM.render(<Mycomponent/>,document.getElementById('text'));

2.props基本使用

props主要应用于外部给组件传递参数

 class Mycomponent extends React.Component{
            render(){
               
                return (
                    <h1>
                        <ul>
                           <li>{this.props.name}</li>   
                           <li>{this.props.age}</li>   
                           <li>{this.props.sex}</li>   

                        </ul>    
                    </h1>
                )
            }
        } 
         let obj = {
             name:'张三',
            age:18,
            sex:'男'
         }
        ReactDOM.render(<Mycomponent {...obj}/>,document.getElementById('text'));

可以给props加入相关检验规则,限制传递的参数

  class Mycomponent extends React.Component{
            static propTypes = {
                name:PropTypes.string.isRequired,
                sex:PropTypes.string,
                age:PropTypes.number
            }
            static defaultProps = {
                sex:'男',
                age:18
            }
            render(){ 
               
                return (
                    <h1>
                        <ul>
                           <li>{this.props.name}</li>   
                           <li>{this.props.age}</li>   
                           <li>{this.props.sex}</li>   

                        </ul>    
                    </h1>
                )
            }
        } 
         let obj = {
             name:'张三',
            age:18,
            sex:'男'
         }
        ReactDOM.render(<Mycomponent {...obj}/>,document.getElementById('text'));

因为函数定义时可以 传递参数,因此函数组件也可以使用props

3. refs用来绑定标签

字符串形式ref

 class Mycomponent extends React.Component{
           showData = ()=>{
               console.log(this.refs)
           }
           render(){
               return(
                   <div>
                        <input ref="ipt1" type="text" />
                        <button onClick = {this.showData}>按钮</button>
                        <input ref="ipt2" type="text" />
                    </div>
               )
           }
       }
       ReactDOM.render(<Mycomponent/>,document.getElementById("text"))

回调形式的ref

在实例自身上挂在节点

内联函数在初次渲染的时候会在{}中执行一次,但是在更新过程会执行两次,第一次传入参数null,第二次 还是标签,原因是创建新的实例的时候会将上一次的ref挂载注销,所以会先null,而类绑定的函数方式则没有这种影响

<script type="text/babel">
       class Mycomponent extends React.Component{
           showData = ()=>{
               console.log(this)
           }
           render(){
               return(
                   <div>
                        <input ref= {c => this.inp1 = c}type="text" />
                        <button onClick = {this.showData}>按钮</button>
                        
                    </div>
               )
           }
       }
       ReactDOM.render(<Mycomponent/>,document.getElementById("text"))

    </script>

钩子函数创建ref

创建一个ref容器只能给一个节点用

  class Mycomponent extends React.Component{
           myRef = React.createRef()
           showData = ()=>{
               console.log(this.myRef)
           }
           render(){
               return(
                   <div>
                        <input ref = {this.myRef}type="text" />
                        <button onClick = {this.showData}>按钮</button>
                        
                    </div>
               )
           }
       }
       ReactDOM.render(<Mycomponent/>,document.getElementById("text"))

4. 高阶函数(函数柯里化)

  1. 高阶函数:将函数作为参数或者返回值的函数。
    1. 如:setInterval、Promis、array.map
  2. 函数柯里化:把接受多个参数的函数变为接受单个参数的函数,并且返回参数 的计算结果
    const sum = (a) => {
        return (b)=>{
            return (c) => {
                return a+b+c;
            }
        }
    }
    
    console.log(sum(1)(2)(3));

     

  3. react中运用高阶函数的案例

 class Mycomponent extends React.Component {
            state = {
                name:'',
                password:''
            }
            show = (name) =>{
                return (e) =>{
                    this.setState({
                        [name]:e.target.value
                    })
                }
            }
            render(){
                return (
                    <form>
                        <div>
                        <label >name:</label>
                        <input  type="text" value={this.state.name} onChange={this.show('name')} / >
                        </div>
                        <div>
                        <label >password:</label>
                        <input type="text" value={this.state.password} onChange={this.show('password')} />
                        </div>    
                    </form>
                )
            }
        }
        ReactDOM.render(<Mycomponent/>,document.getElementById('text'));

不用柯里化的写法:

  class Mycomponent extends React.Component {
            state = {
                name:'',
                password:''
            }
            show = (name,e) =>{
                this.setState({
                    [name]:e.target.value
                })
            }
            render(){
                return (
                    <form>
                        <div>
                        <label >name:</label>
                        <input  type="text" value={this.state.name} onChange={(e)=>{this.show('name',e)}} / >
                        </div>
                        <div>
                        <label >password:</label>
                        <input type="text" value={this.state.password} onChange={(e)=>{
                            this.show('password',e)
                        }} />
                        </div>    
                    </form>
                )
            }
        }
        ReactDOM.render(<Mycomponent/>,document.getElementById('text'));

 

第三章 组件的生命周期

基本上旧版本的生命周期就按照上图所示,值得注意的是:

  1. shouldComponentUpdata 默认返回true
  2. componentWillReceiveProps在子组件第一次挂在接受props不会调用,在后续传入新的props是才调用

 

新的生命周期和旧的生命周期相比,废除了三个钩子,新加了两个钩子。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

问也去

创作不易,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值