react学习笔记

学习视频地址:https://www.bilibili.com/video/BV1wy4y1D7JT

1. React简介

  • React是用于构建用户界面的javascript库。
  • 由Facebook开发,且开源。
  • React的特点:
    1.采用组件化模式、声明式编码,提高开发效率及组件复用率。
    2.在React Native中可以使用React语法进行移动端开发
    3.使用虚拟DOM+优秀的Diffing算法,尽量减少与真实DOM的交互。

注:

  • 虚拟DOM会比较新、旧两个虚拟DOM,只渲染改变的部分(当数据量大时效率更高)。
    在这里插入图片描述
  • 而原生js实现(直接操作真实DOM)没有虚拟DOM这个环节,会重新渲染整个页面。
    在这里插入图片描述

2. React的基本使用

  1. 准备好一个容器
  2. 引入3个依赖 (react、react-dom、babel)
  3. 创建虚拟DOM,并渲染到页面
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>hello_react</title>
  </head>
  <body>
    <!-- 1.准备好一个容器 -->
    <div id="test"></div>

    <!-- 2.引入依赖 -->
    <!-- react核心库,必须在react-dom扩展库之前引入 -->
    <script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script>
    <!-- react-dom扩展库,用于支持React操作DOM -->
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script>
    <!-- 将jsx翻译为js(浏览器本身不能识别jsx) -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <!-- 3.创建虚拟DOM,并渲染到页面 -->
    <!-- type="text/babel"表示内部写的是jsx,并且用babel翻译(不写默认是js) -->
    <script type="text/babel">
      // 3.1.创建虚拟DOM,jsx语法
      const VDOM = (
        <h1>
          hello react
        </h1>        
      )
      // 3.2.渲染虚拟DOM到页面(这是一个替换页面的过程)
      ReactDOM.render(VDOM, document.getElementById('test')) 
    </script>
  </body>
</html>

2.1 虚拟DOM的两种创建方式

1.使用jsx创建

	<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <script type="text/babel">
      const VDOM = (
        <h1 id="title">
          hello react
        </h1>        
      )
      ReactDOM.render(VDOM, document.getElementById('test')) 
    </script>

2.使用js创建

    <script type="text/javascript">
      // React.createElement(标签名, 标签属性, 标签内容)
      const VDOM = React.createElement('h1', {id: 'title'}, 'Hello React')
      // 2.渲染虚拟DOM到页面(这是一个替换页面的过程)
      ReactDOM.render(VDOM, document.getElementById('test')) 
    </script>

注:

使用js创建虚拟DOM,不用babel翻译,但是写法繁琐。
而jsx是这种写法的语法糖,通过babel翻译后的形式与js创建虚拟DOM的形式相同。

2.2 虚拟DOM与真实DOM

  • 虚拟DOM
    1.本质是Object类型的对象
    2.虚拟DOM比较"轻",真实DOM比较"重",因为虚拟DOM是React内部在用,无需真实DOM那么多属性
    在这里插入图片描述
    3.虚拟DOM最终会被React转化为真实DOM,呈现在页面上

2.3 jsx

  1. 定义虚拟DOM时,不用写引号

  2. 标签中混入js表达式时要用{}

注:

{}中只能写js表达式,不能写js语句

  1. 表达式:一个表达式会产生一个值。(下面这些都是表达式)
    a
    a+b
    demo(1)
    arr.map()
    function text(){}
  2. 语句:(下面这些都是语句)
    if(){}
    for(){}
    .switch(){case:XXXX}
  1. 样式的类名指定不要用class,要用className

  2. 内联样式,要用style={{key:value}}的形式去写

  3. 只有一个根标签

  4. 标签必须闭合

  5. 标签首字母

    (1).若小写字母开头,则将该标签转为html中同名元素,若html中没有,则报错

    (2).若大写字母开头,则将该标签转为组件,若组件没有定义,则报错

示例:

<script type="text/babel">
  const myId = "hello"
  const VDOM = (
    <div>
      <h1 className="myH1" id={myId.toLowerCase()} style={{color:'red',fontSize:'20px'}}>
        hello react
      </h1>
      {
        //浏览器报错,html标签中没有good标签
      }
      <good>123</good>
      {
        //Good为组件,需要定义该组件,否则报错
      }
      <Good>123</Good>
    </div>        
  )
  ReactDOM.render(VDOM, document.getElementById('test')) 
</script>

2.3.1 jsx小练习

动态渲染数据至页面

<script type="text/babel">
  const data = ['angular', 'react', 'vue']
  const VDOM = (
    <ul>
      {
        data.map((r,i) => <li key={i}>{r}</li>)
      }
    </ul>        
  )
  ReactDOM.render(VDOM, document.getElementById('test'))
</script>

2.4 模块化与组件化

模块:向外提供特定功能的js程序,一般就是一个js文件
组件:实现局部功能效果的代码和资源的集合(html、css、js、img、vedio、font…)

2.5 定义组件

2.5.1 函数式组件

简单组件

function Demo(){
    console.log(this) //此处的this是undefined,因为babel编译后开启了严格模式
    return <h2> 函数式组件(简单组件)</h2>
}
// 解析组件标签,找到组件并调用该函数,将虚拟DOM转化为真实DOM,并渲染到页面
ReactDOM.render(<Demo/>, document.getElementById('test')) 

2.5.2 类式组件

复杂组件:有状态

class Demo extends React.Component{
    // render放在类的原型对象上,供实例使用
    render(){
        // this指向Demo组件 实例对象
    	console.log(this)
        return <h2> 类式组件(复杂组件)</h2>
    }
}
// 解析组件标签,找到组件并new出该类的实例,并通过该实例调用原型上的render方法,将虚拟DOM转化为真实DOM,并渲染到页面
ReactDOM.render(<Demo/>, document.getElementById('test')) 

注:

  1. 类中的构造器不是必须写的。要对实例进行一些初始化操作,如添加指定属性时才写。
  2. 如果A类继承了B类,且A类中写了构造器,那么A类构造器中必须调用super。
  3. 类中定义的方法,都是放在类的原型对象上,供实例去使用。

类的相关知识点示例:

class Person{
  // 构造方法
  constructor(name, age){
    // 构造器中的this指向类的实例对象
    this.name = name
    this.age = age
  }
  // 一般方法
  // speak方法放在类的原型对象上,供实例使用
  // 通过Person实例调用speak方法时,speak中的this就是Person实例
  speak(){
    console.log(`my name is ${this.name}, my age is ${this.age}`)
  }
}
const p1 = new Person('tom', 12)
p1.speak()
class Student extends Person{
  constructor(name, age, sex){
    super(name, age)
    this.sex = sex
  }
  // 重写从父类继承过来的方法
  // 通过Student实例调用speak方法时,speak中的this就是Student实例
  speak(){
    console.log(`my name is ${this.name}, my age is ${this.age}, I am a ${this.sex}`)
  }
}
const s1 = new Student('tim', 13, 'girl')
s1.speak()

2.6 组件实例的三大核心属性

由class创建的组件,才有组件实例,才有三大核心属性

2.6.1 state

用途:存储组件自身的数据
获取状态数据:this.state.xxx
更改状态数据:this.setState({xxx:xxx}),传入的对象会合并原先的state对象

class Demo extends React.Component{
    //构造器执行1次,初始化状态,解决this指向问题
    constructor(props){
        super(props)
        this.state = {
            isHot: false
        }
        // 这里的this是组件实例对象
        // 将原型链中的this.btnClick方法挂载到了实例自身上
        this.btnClick = this.btnClick.bind(this)
    }
    btnClick(){
        //btnClick放在原型对象上
        //通过Demo实例调用btnClick时,this才指向Demo实例
        //调用该方法时btnClick是onClick的回调,不是通过实例调用的,是直接调用,this会丢失
        //由于类中的方法默认开启了严格模式,所以this指向undefined
        this.setState({
            //合并
            isHot: !this.state.isHot
        })
    }
    // render放在类的原型对象上,供实例使用
    // onClick必须绑定一个函数,不能是函数调用表达式
    // render调用1+n次,1是初次渲染,n是状态更新的次数
    render(){
    	// render中的this就是组件实例对象
    	console.log(this)
        const {isHot} = this.state
        return (
            <div>
            <h2>今天天气很{isHot ? '炎热' : '凉爽'}</h2>
			<button onClick={this.btnClick}>切换</button>
			</div>
		)
	}
}
// 解析组件标签,找到组件并new出该类的实例,并通过该实例调用原型上的render方法,将虚拟DOM转化为真实DOM,并渲染到页面
ReactDOM.render(<Demo/>, document.getElementById('test')) 

注:

this指向

  1. onClick方法绑定的是函数,不能写成下面这种形式,下面这种形式会直接调用(调用的话会在render页面的时候就触发,变为绑定undefined方法)
    onClick={this.btnClick()}
  2. onCLick绑定方法时,是回调函数,是直接调用,不是实例调用,所以this会丢失
  3. this.btnClick = this.btnClick.bind(this)会把原型上的btnClick 方法绑定到实例上。并在实例对象上生成一个新的btnClick 方法,从而覆盖原型上的btnClick 方法。

效果:
在这里插入图片描述
点击切换
在这里插入图片描述
简写:

  1. 简写state
    类中可以直接写赋值语句。
    通过赋值语句为state赋值,即直接在实例对象上添加了state属性
  2. 简写方法
    通过赋值语句添加方法,即直接在实例对象上添加了方法
    通过箭头函数添加方法时,方法中的this指向实例对象
class Demo extends React.Component{
  //添加到实例对象上(state是一个对象)
  state = {
      isHot: false
  }
  // 自定义方法----赋值语句+箭头函数
  btnClick = () => {
    //箭头函数中的this找到箭头函数外部的this,为Demo的实例对象
    this.setState({
      isHot: !this.state.isHot
    })
  }
  render(){
    const {isHot} = this.state
    return (
      <div>
        <h2>今天天气很{isHot ? '炎热' : '凉爽'}</h2>
        <button onClick={this.btnClick}>切换</button>
      </div>
    )
  }
}
ReactDOM.render(<Demo/>, document.getElementById('test')) 

2.6.2 props

只读,不能修改
用途:接收传入组件的参数
获取props:this.props.xxx

class Demo extends React.Component{
  render(){
    const {name, sex, age} = this.props 
    return (
      <ul>
        <li>姓名:{name}</li> 
        <li>性别:{sex}</li> 
        <li>年龄:{age}</li>
      </ul>
    )
  }
}
const p = {name:'zs', sex:'女', age:'18'}
//批量传递标签属性(props)
ReactDOM.render(<Demo {...p} />, document.getElementById('test')) 

备注:(展开运算符)

let person = {name:'zs', sex:'女', age:'18'}
console.log(...person) //报错,展开运算符不能展开对象
let person2 = {...person} //可以复制一个对象
2.6.2.1 对props进行类型限制,设置默认值

我的限制没出现警告,不知道为啥???

<!-- 要使用PropTypes,必须引入PropTypes的包 -->
<script src="https://unpkg.com/prop-types@15.6/prop-types.js"></script>
<script type="text/babel">
    class Demo extends React.Component{
      render(){
        const {name, sex, age} = this.props 
        return (
          <ul>
            <li>姓名:{name}</li> 
            <li>性别:{sex}</li> 
            <li>年龄:{age + 1}</li>
          </ul>
        )
      }
    }
    //对props进行限制,这里propTypes的p小写
    Demo.propTypes = {
      // 要使用PropTypes,必须引入PropTypes的包,这里PropTypes的P大写
      name: PropTypes.string.isRequired, 
      sex: PropTypes.string, //第一个字母都是小写,不会与内置的String冲突
      age: PropTypes.number,
      speak: PropTypes.func //function是关键字,这里改写成func
    }
    Demo.defaultProps = {
      sex: '不详',
      age: 18
    }
    const p = {sex:'女'}
    ReactDOM.render(<Demo {...p} />, document.getElementById('test')) 
</script>

简写:
通过static关键字,可以为组件类自身添加属性

class Demo extends React.Component{
  // 添加static关键字,给Demo自身添加属性
  static propTypes = {
    // 要使用PropTypes,必须引入PropTypes的包
    name: PropTypes.string.isRequired, 
    sex: PropTypes.string,
    age: PropTypes.number,
    speak: PropTypes.func
  }
  static defaultProps = {
    sex: '不详',
    age: 18
  }
  render(){
    const {name, sex, age} = this.props 
    return (
      <ul>
        <li>姓名:{name}</li> 
        <li>性别:{sex}</li> 
        <li>年龄:{age + 1}</li>
      </ul>
    )
  }
}
2.6.2.2 函数式组件使用props
function Demo(props){
  const {name, sex, age} = props 
  return (
    <ul>
      <li>姓名:{name}</li> 
      <li>性别:{sex}</li> 
      <li>年龄:{age + 1}</li>
    </ul>
  )
}
    //对props进行限制,这里propTypes的p小写
    Demo.propTypes = {
      // 要使用PropTypes,必须引入PropTypes的包,这里PropTypes的P大写
      name: PropTypes.string.isRequired, 
      sex: PropTypes.string, //第一个字母都是小写,不会与内置的String冲突
      age: PropTypes.number,
      speak: PropTypes.func //function是关键字,这里改写成func
    }
    Demo.defaultProps = {
      sex: '不详',
      age: 18
    }
const p = {name:'zs', sex:'女', age:12}
ReactDOM.render(<Demo {...p} />, document.getElementById('test')) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值