React基础知识学习

React是由Facebook进行维护的。
React是什么?

React是一个声明式,高效且灵活的用于构建用户界面的JavaScript库,使用React可以将一些简短、独立的代码片段组合成复杂的UI界面,这些代码片段被称为”组件“。

React语法
jsx语法
  1. React框架主要使用jsx语法(js混合html一起书写的)。但是它又和html语法不太一样,和XML语法比较相似。
    ①标签必须要有结束符号(例如:<input />,无论是单标签还是双标签都要有这个闭合符号/)。
    ②标签的属性一律使用驼峰命名法(例如:html5中的data-index属性在这里提倡dataIndex这种写法)。
    ③类名必须用className进行命名,才会生成class。 (注意:vue.js框架也支持jsx语法)
  2. jsx语法的本质?
<!--使用jsx语法  -->
<script type='text/babel'>
    const title = <h1>我是大标题</h1>
    ReactDOM.render(title,document.getElementById('root'))
</script>
//不使用jsx语法
//上面的jsx语法会最终编译成下面的代码
<script>
    const title = React.createElement('h1',{
        className: 'title',
        style: {
            color:#f00
        }
    },'我是大标题');
    ReactDOM.render(title,document.getElement('root'))
</script>

打印出title的值:console.log(title)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200121235951228.png![在这里插入图片描述](https://imgblog.csdnimg.cn/20200122000125281.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0w4NjM2ODMzMDU=,size_16,color_FFFFFF,t_70)(注意:vue中也有这样的写法)
3. jsx语法上的一些api?

<script type='text/babel'>
    const str = '我是字符串';
    const num = 998;
    //在jsx语法中,凡是false相关的值,默认不渲染,这一点是和vue相一致的。
    //如果想要让undefined显示出来,只需要将它转为字符串即可。例如:
    //const none = String(undefined) 
    const none = undefined; //false,none等也不显示
    const person = {
        firstName: '唐',
        lastName: '老鸭'
    };
    function getFullName(firstName,lastName) {
        return firstName + lastName
    };
    const sexNum = 1;
    const element = (
        <div>
            <ul>
                <li>{str}</li>
                <li>{num}</li>
                <li>{none}</li>
                <li>{getFullName(person.firstName,person.lastName)}</li>
                <li>我是一个{sexNum == 1 ? '男' : '女'}孩</li>
            </ul>
        </div>
    )
    ReactDOM.render(element,document.getElementById('root'))
</script>

得到如下结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZWJcB1uF-1579622141463)(3AE71BB7F8D84E3E8D32BDB6114FB220)]
例子:用react实现if方法

<script type='text/babel'>
    const sexNum = 1;
    let str = '';
    if(sexNum == 1) {
        <!--想让它具有vue中v-if类似的效果,可以直接设置为-->
        <!--none,false,undefined-->
        str = '我是男孩' 
    }else {
        str = '我是女孩'
    }
    const element = {
        <div>{str}</div>
    }
    ReactDOM.render(element,document.getElementById('root'))
</scritp>
元素的渲染

react高性能的优势:使用一个对象去描述一个dom。
diff算法:
例如:

//原始的jsx 
{
    type: 'p',
    props: {
        children: '2019/10/29 下午 17:40:14'
    }
}
//新的对象
{
    type: 'p', //这一部分因为一样,不需要修改
    props: {
        //只需要修改这一部分
        children: '2019/10/29 下午 17:40:30'
    }
}
//diff算法 ==》得出需要修改的最小部分为children 
//==》p.innerText='新的children'

这就是react内部的原理。

组件
  1. 组件渲染和元渲染的不同点:
    ①元素更偏向于html/css部分。
    ②组件更偏向于将html/css/js逻辑层封装到一起。
    ③组件可以进行复用,而元素不可以。
//元素渲染
let data = new Date();
let day = data.getDay();
const element = (
    <div>
        <h1>今天是星期{day}</h1>
    </div>
)
ReactDOM.render(element,getElementById('root'))

//组件渲染在react有两种写法,组件一律使用大写字母开头。
//第一种:用函数,函数是最简单的组件。
function Element () {
    let data = new Date();
    let day = data.getDay();
    return (
        <h1>今天是星期{day}</h1>
    )
}
function Container () {
    return (
        <div>
            <h1>这是描述时间的页面</h1>
            <Element />
            <Element />
        </div>
    )
}
ReactDOM.render(<Container />,document.getElementById('root'))


//父子传值
function Element (params) {
    console.log(params)
    return (
        <div>
            <h1>今天是星期{params.day}</h1>
        </div>
    )
}
function Container () {
    let data = new Date();
    let day = data.getDay();
    return (
        <div>
            <h1>正在进行父子传值</h1>
            <Element day={day} abc='1,2,3'/>
            <Element day={day}>
        </div>
    )
}
ReactDOM.render(<Container />,document.getElementById('root'))

//注意:如果想要修改后的变量值重新渲染到页面上,必须重新调用
//render函数,否则只是会修改,但不会重新渲染到页面上。但这是函数组件无法做到的。
//第二种组件渲染:类组件
<script type='text/babel'>
//使用解构赋值 const {Component} = React  
    class Clock extends React.Component {
    //class Clock extends Component
        constructor (props) {
            super (props)
        }
    }
    render () {
        return (
            <div>
                <h1>今天是星期{this.props.day}</h1>
            </div>
        )
    }
    class Container extends React.Component {
        constructor (props) {
            super(props)
            this.state = {
                day: new Date().getDay()
            }
        }
        changeDay () {
            console.log(this.state.day)
            this.setState = ({//可以把它当做是一个异步操作
                day:4
                //如果想要获得实时更改后的值,可以通过一个回调函数。
            },function(){
                console.log(this.state.day)
            })
        }
        render () {
            return (
                <div>
                    <h1>我是显示时间的页面</h1>
                    <button onClick={this.changeDay.bind(this)}>修改</button>
                    <Clock day={this.state.day}/>
                    <Clock day={this.state.day}/>
                </div>
            )
        }
    }
    ReactDOM.render(<Container/>,document.getElementById('root'))
    //'React.Component'每次写这么长的代码比较麻烦,我们可以使用
    //es6解构赋值:const {Component} = React
 </script>

在react中,想要重新渲染页面,只有一个方法,那就是重新执行render函数。
在类组件中,存在一些生命周期,修改某一项值,会触发render的修改。
①修改类组件中的state(setState)会触发页面的更新。
②修改类组件中的props会触发组件的更新。

注意:

函数组件无法进行页面的重新渲染,类组件通过修改某一项值可以进行页面的重新渲染。

React生命周期(定义组件都以类的方式去定义组件,因为类组件有生命周期,函数组件没有生命周期)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8xKzEFxT-1579622141464)(F86E266CB68B4E898AB71AFEED759CBA)]
React生命周期主要包含三个阶段:初始化阶段、运行中阶段和销毁阶段,在React不同的生命周期里,会依次触发不同的钩子函数。

一、初始化阶段
  1. 设置组件的默认属性
static defaultProps = {
    name: 'sls',
    age:23
};
//or
Counter.defaltProps = {name:'sls'}
  1. 设置组件的初始化状态
constructor () {
    super();
    this.state = {number:0}
}
  1. componentWillMount()
组件即将被渲染到页面之前触发,此时可以进行开启定时器、
向服务器发送请求等操作
  1. render()
组件渲染
  1. componentDidMount()
组件已经被渲染到页面中后触发:此时页面中有了真正的DOM元素,
可以进行DOM相关的操作
二、运行中阶段
  1. componentWillReceiveProps()
组件接收到属性时触发
  1. shouldComponentUpdate()
当组件接收到新属性,或者组件的状态发生改变时触发。
组件首次渲染时并不会触发。
shouldComponentUpdate(newProps,newState) {
    if(newProps.number < 5) return true;
    return false
}
//该钩子函数可以接收到两个参数,新的属性和状态,
//返回true/false来控制组件是否需要更新。
一般我们通过该函数来优化性能:
一个React项目需要更新一个小组件时,很可能需要父组件更新自己
的状态。而一个父组件的重新更新会造成它旗下所有的子组件重新执
行render()方法,形成新的虚拟DOM,再用diff算法对新旧虚拟DOM
进行结构和属性的比较,决定组件是否需要重新渲染。
但是这样的操作会造成很多性能浪费,所以我们开发者可以根据项目
的业务逻辑,在shouldComponentUpdate()中加入条件判断,从而
优化性能。
例如React中就提供了一个PureComponent的类,当我们的组价
继承于它时,组件更新时就会默认先比较新旧属性和状态,从而
决定组件是否更新。值得注意的是,PureComponent进行的是浅比
较,所以组件状态或属性改变时,都需要返回一个新的对象或数组
。
  1. componentWillUpdate()
组件即将被更新时触发
  1. componentDidUpdate()
组件被更新完成后触发。页面中产生了新的DOM的元素,可以进行DOM操作。
三、销毁阶段
  1. componentWillUnmount()
组件被销毁时触发。这里我们可以进行一些清理操作,例如清理定时器,取消Redux的订阅事件等等。
四、整个生命周期代码
<script type='text/babel'>
   const {Component} = React
   class SubCounter extends Component {
       componentWillReceiveProps() {
           console.log('9:componentWillReceiverProps:子组件将要接收到新的属性')
       }
       shouldComponentUpdate(newProps,newState){
           console.log('10:shouldComponentUpdate:子组件是否需要更新')
           if(newProps.number < 5) return true
           return false
       }
       componentWillUpdate () {
           console.log('11:componentWillUpdate:子组件将要更新')
       }
       componentDidUpdate () {
           console.log('13:componentDidUpdate:子组件更新完成')
       }
       componentWilUnmount () {
           console.log('14:componentWillUnmount:子组件将卸载')
       }
       render() {
           console.log('12:render:子组件挂载中')
           return (
               <p>{this.props.number}</p>
           )
       }
   }
   class Counter extends Component {
       static defaultProps = {
           //1.加载默认属性
           name: 'sls',
           age:23
       }
       constructor (props) {
           super(props);
           //2.加载默认状态
           this.state = {number:0}
       }
       componentWillMount () {
           console.log('3:componentWillMount:父组件挂载之前')
       }
       componentDidMount () {
           console.log('5:componentDidMount:父组件挂载完成')
       }
       shouldComponentUpdate(newProps,newState) {
           console.log('6:shouldComponentUpdate:父组件是否需要更新')
           if(newState.number < 5) return true
           return false
       }
       componentWillUpdate () {
           console.log('7:componentWillUpdate:父组件将要更新')
       }
       componentDidUpdate () {
           console.log('8:componentDidUpdate:父组件更新完成')
       }
       handleClick = function () {
           this.setState ({
               number:this.state.number + 1
           })
       }
       render () {
           console.log('4:render:父组件挂载')
           return (
               <div>
                  <p>{this.state.number}</p>
                  <button onClick = {this.handleClick.bind(this)}>点我+1</button>
                  {this.state.number < 10 ? <SubCounter number={this.state.number}/> : null}
               </div>
           )
       }
   }
</script>

进行打印:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1S3YyFPt-1579622141465)(AD64D1D4BD664DAA8525E6D4F1C4F8BB)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-llO11taw-1579622141466)(BE058894CCBD4702B0F8E4EC5589ACB0)]

this指向

this的几种不同的使用场景,也就是函数调用时this的指向:
①纯函数调用this指向Window。
②事件调用:谁调用这个函数,this就指向谁。
③定时器调用:在定时器中,this指向window。
④构造函数调用:构造函数生成一个新的对象,this指向新建的这个对象。

apply()、call()、bind()三者都能改变this的指向,且第一个参数都是this的指向对象。第二个参数有所区别:

call的第二个参数往后:call的参数是直接放进去的,第二第三第n个参数全都用逗号分隔,直接放到第一个参数后面。
apply的第二个参数往后:所有参数都必须放进一个数组里面传进去。
bind除了返回的是一个新函数以外,你必须调用它才会被执行。它的参数和call一样。
当然,三者的参数不限定是String,允许是各种类型,包括函数、object等等!
实例:

<!--this永远指向调用它的对象-->
<!--this的指向只有调用的时候才知道-->
<!--箭头函数的this的指向是在定义的时候就已经绑定了-->
<script>
   var name = 'window 的name'
   var obj = {
       name: '王力宏'
       printName () {
           console.log(this.name)
       }
   }
   obj.printName() //王力宏
   
   const fn = obj.printName //引用数据类型
   //fn只是保存了obj.printName这个引用数据类型的地址
   fn() //window 的name  fn()==>window.fn()
</script>

react核心代码之this指向

<body>
   <button id='btn'>点我</button>
</body>
<script>
   var name = 'window 的name'
   class Demo {
       constructor () {
           this.name = '我是demo'
           this.demo = document.getElementById('btn')
           const _this = this
          //this.demo.onclick = function() {
          //     _this.printSome()
          // }
          
          //react核心代码之this指向
           const fn = this.PrintSome
           this.demo.onclick = function () {
               fn.bind(_this)()
           }
       }
       printSome () {
           console.log(this)
       }
   }
  
</script>
事件处理中的this
'use strict' //严格模式,es6当中推出来的,在严格模式中,
//禁止变量未定义就直接使用,以及规定了,全局调用的函数的this的指向指向undefined。

注意:事件处理函数是没有办法传参的(在原生中,在vue或者react中,别人已经封装过了,可以传参)!

在react框架的事件处理函数中(例如:点击事件原生是onclick全小写,而react使用驼峰命名法onClick,vue是(@click))。原因是事件处理函数已经被react框架进行了封装。原生的点击事件onclick是无法进行传参的。而react和vue中的点击事件是可以传参的。

//以vue为例,进行源码的解读
<script>
   let demo = {
       template: `
           <div>
               <button @click = handleClick($event,123)></button>
           </div>
       `,
       methods: {
           handleClick($event,num) {
               console.log($event,num)
           }
       }
   }
   let vm = new Vue({
       el: '#app',
       data: {},
       components: {demo}
   })
   
</script>
<!--vue和react封装的事件处理函数类似,此处以点击事件为例:-->
<!--const fn = this.handleClick()-->
<!--let btn = document.getElementById('btn')-->
<!--const _this = this-->
<!--btn.onclick = function () {-->
<!--    fn.call(_this,e,123)-->
<!--}-->
不足之处,请多多指教
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值