react的基础知识详细介绍

1、关于虚拟DOM

本质是Object类型的对象(一般对象);

虚拟DOM比较’轻‘,真实DOM比较’重‘,因为虚拟DOM 是react内部在用,无需真实DOM 上那么多的属性;

虚拟DOM最终会被react转化成真实DOM,呈现在页面上;

2、js代码(语句)与js表达式

(1)表达式

一个表达式会产生一个值,可以放在任意一个需要值的地方;
下面这些都是表达式:
a;
a+d;
demo(1);
arr.map();
function test(){};

(2)语句

if(){};
for(){};
switch(){case:};

3、模块、组件、模块化与组件化的理解

(1)模块

向外侧提供特定功能的js程序,一般都是一个js文件;

为什么要拆成模块:随着业务功能增多,代码越来越多且复杂;

作用:复用js,简化js的编写,提高Js运行效率;

(2)组件

用来实现局部功能效果的代码和资源的集合HTML/CSS/JS/IMAGE等等;

为什么:一个界面的功能越复杂;

作用:复用编码,简化项目编码,提高运行效率;

(3)模块化

当应用的js都以模块来编写的,这个应用就是一个模块化的应用;

(4)组件化

当应用是以多组件的方式实现,这个应用就是一个组件化的应用;

4、jsx语法规则

定义虚拟DOM时,不要写引号;

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

样式的类名指定不要使用class,要使用className;

内联样式,要用style={{key:value}};

只有一个根标签;

标签必须闭合;

标签首字母:若是小写开头,则将该标签转化为html同名元素,若html中无该标签对应的同名元素,则报错;若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错;

5、函数组件

<script type='text/babel'>
 //1、创建函数组件
 function MyComponent(){
 console.log(this);//此处的This是undefined,因为babel编译后开启了严格模式;
 return <h2>我是用函数定义的组件(仅适用于简单的组件)的定义</h2>
 //2、渲染组件到页面
 ReactDOM.render(<MyComponet />,document.getElemetById('text'))
 /*
 执行ReactDOM.render(<MyComponent/>...)之后,发生了什么?
 React解析组件标签,找到MyComponent组件;
 发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中;
 *
 /
 }
</script>

6、类的基础知识

(1)创建一个Person类

class Person {
//构造器方法
constructor(name,age){
//构造器中的This是谁?---类的实例对象
this.name =name;
this.age = age;
}
//一般方法
speak(){
//speak方法放在了哪里?--类的原型对象上,供实例使用
//通过Person实例调用speak时,speak中的this就是Person实例
console.log(`我叫${this.name},我今年${age}岁`)
}
}

(2)创造一个Student类,继承Person类

class Student extends Person {
cnstructor(name,age,grade){
super(name,age);
this.grade = grade;
}
//重写从父类中继承过来的方法
speak(){
consoloe.log(`我叫${this.name},我今年${this.age},我读的是${this.grade}年级`)
}
study(){
//study方法放在了哪里?---类的原型对象上,供实例使用
//通过Student实例调用study时,study中的this就是Student实例
console.log('我很努力的学习')
}
}

(3)总结

类中的构造器不是必须要写的,要对实例进行一些初始化的操作,如添加指定属性时才写;

如果A类继承了B类,且A类中写了构造器,那么A类中的super是必须要调用的;

类中所定义的方法,都是放在了类的原型对象上,供实例去使用;

7、创建类式组件

class MyComponent extends React.Component{
render(){
   //render是放在哪里的?---MyComponent的原型对象上,供实例使用
   //render中的this是谁?---MyComponent的实例对象《=》MyComponent组件实例对象
   return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
   }
}
//渲染组件到页面
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
/*
执行了ReactDOM.render(<MyComponent/>,...)之后,发生了什么?
React解析组件标签,找到对应的组件
发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用原型上的render方法
将render返回的虚拟DOM转为真实的DOM,随后呈现在页面中*/

8、组件实例的三大核心属性

(1)state

state是组件对象最重要的属性,值是对象(可以包含多个key-value的组合);

组件被称为“状态机”,通过更新组件的state来更新对应的页面显示(重新渲染组件);

组件中render方法中对应的this为组件实例对象;

组件自定义中的this为undefined,如何解决?箭头函数;强制绑定this:通过函数对象的bind();

状态数据不能直接修改或更新;

render(){
  return <h2 onClick = {this.changeWeather}>今天的天气很{isHot}</h2>
}
changeWeather(){
 //changeWeather放在哪里?---Weather的原型对象上,供实例使用;
 //由于changeWeather是作为onClick的回调函数,所以不是通过实例调用,是直接调用
 //类中的方法,默认开启了局部严格模式,所以changeWeather中的this为undefined
 console.log(this);
}

(2)props

每个组件对象都会有自己的props属性;

组件标签的所有属性都保存在props中;

通过标签属性从组件外向组件内传递变化的数据;

注意:组件内部不要修改props数据;

内部读取某个属性值:this.props.name;

扩展属性:将对象的所有属性通过props传递(在这里可以使用…的方式来进行);

class Person extends React.Component{
render(){
  console.log(this);
  const {name,age,sex} = this.props;
  return (<ul>
         <li>姓名:{name}</li>
         <li>性别:{sex}</li>
         <li>年龄:{age}</li>
         </ul>)
       }
}
const p ={naem:'老刘',age:18,sex:'女'};
ReactDOM.render(<Person {...p}/>,document,getElementById('text'));//在这里...可以理解成解构

…解构的作用

let arr = [10,20,30,40];
let arr2 = [20,70,80,90,60];
console.log(...arr);//展开一个数组
let arr3 = [...arr,...arr2];//连接数组
//在函数中使用
function sum(...number){
  return number.reduce((pre,new)=>{
    return pre + new 
  })
}
console.log(sum(1,2,3,4))
//构造字面量对象时使用展开语法
let person ={name:'tom',age:18 };
let person2 = {...person};
console.log(...person);//报错,展开运算符不能展开对象
person.name = 'nana';
console.log(person);
console.log(person2);

//合并
let person3 = {...person,name:'jack',address:'地球'};
console.log(person3)

在传递的过程中,可以进行传递属性的设置

//对标签属性进行类型和必要性的限制
Person.propTypes = {
 name:PropTypes.string.isRequired,//限制name必传,且为字符串
 sex:PropTypes.string,//限制sex为字符串
 age:PropTypes.number,//限制age为数值
 speak:PropTypes.func,//限制speak为函数
}
//指定默认标签属性值
Person.defaultProps = {
   sex:'男',//sex默认值为男
   age:18//age默认值为18
}

构造器是否接收props,是否传递给super,取决于是否希望在构造器中通过this访问props

(3)ref

回调函数形式的ref(当将函数体写成内联样式的时候,会产生执行次数的问题)

//创建组件
class Demo extends React.Component{
   showInfo = ()=>{
   //将节点从实例中取出来
   const {input} = this;
   alert(input.value)
  }
  render(){
  return (
     <div>
         //写成内联的样式,会出现当页面重新刷新的情况下,多次调用ref中函数体,但是这个问题在实际的开发中无伤大雅,具体的说法可以参考官方文档
         <input ref = {(currentNode)=>{this.input = currentNode}} type='text' />
         <button onClick = {this.showInfo}>点我提示输入的数据</button>
     </div>)
  }
}
//渲染组件到页面
ReactDOM.render(<Deom />,document.getElementById('test'))

createRef

//创建组件
class Demo extends React.Component{  
   /*
   React.createRef调用后可以返回一个容器,该容器可以存储被ref所标的节点,该容器是专人专用的
   */
   myRef = React.createRef();
   showInfo = ()=>{   
        alert(this.myRef.current.value)
         }  
    render(){  
    return (     
    <div>  
    <input ref = {this.myRef} type='text' />                   
    <button onClick ={this.showInfo}>点我提示输入的数据</button>     
    </div>)  }}
    //渲染组件到页面
 ReactDOM.render(<Deom />,document.getElementById('test'))

字符串形式ref现在已经不推荐使用了,或许在后期的版本中会被废除,但此形式却是最简单的一种方式

9、事件处理

(1)通过onxxx属性指定事件处理函数(注意大小写)

React使用的是自定义(合成)事件,而不是使用的原生DOM事件 —为了更好的兼容性

React中事件是通过事件委托方式处理的(委托给组件最外层的元素)—为了高效

(2)通过event.target得到发生事件的DOM对象—不要过度使用ref

10、非受控组件和受控组件

11、高阶函数、函数柯里化

(1)高阶函数
如果一个函数符合下面2个规范中的任何一个,那么该函数就是高阶函数

a、若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数

b、若A函数,调用的返回值仍然是一个函数,那么A就可以称之为高阶函数

常见的高阶函数有:Promise/setTimeout/arr.map(数组的一些方法)等等

(2)函数的柯里化

通过函数调用继续返回函数的方式,实现多次接收参数,最后统一处理的函数编码形式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
    <div id='test'></div>
    <script type='text/babel'>
    // 创建组件
    class Login extends React.Component{
        // 状态的初始化
        state = {
            username:'',
            password:''
        }
        // 表单提交的回调
        handleSubmit = (event)=>{
            // 利用事件对象阻止默认事件,在这里是阻止了表单的提交
            event.preventDefault();
            const {username,password} = this.state;
            alert(`用户名为:${username},输入的密码为:${password}`)
         
        }
        // onChange事件中,是将saveFormData返回值作为回调函数,要想让onChange不断去触发,则返回值需要是一个函数
        // 此为高阶函数
        saveFormData = (dataType)=>{
            return ((event)=>{
            //   console.log([dataType],event.target.value)//通过打印可以发现,这句话只要输入框中的内容有变化,此打印语句就会被出发
              this.setState({
                //dataType只是一个字符串,我们需要的是dataType中的值,所以在这里需要加方括号
                [dataType]:event.target.value
              })
          })
        }
        render(){
            return(
                <form onSubmit = {this.handleSubmit}>
                    
                    用户名:<input type="text" name='username' onChange = {this.saveFormData('username')} />
                    密码:<input type="password" name='password' onChange = {this.saveFormData('password')}/>
                    <button>登录</button>
                </form>
            )
        }
    }
    // 渲染组件到页面中
    ReactDOM.render(<Login/>,document.getElementById('test'))
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 第一种
        // function sum (a,b,c){
        //     return a+b+c;
        // }
        // let result = sum(1,2,3)
        // console.log(result)
        // 函数的柯里化
        function sum(a){
            return (b)=>{
                return(c)=>{
                 return a+b+c
                }

            }
        }
        let result = sum(1)(2)(3)
        console.log(result)
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
    <div id='test'></div>
    <script type='text/babel'>
    // 创建组件
    class Login extends React.Component{
        // 状态的初始化
        state = {
            username:'',
            password:''
        }
        // 表单提交的回调
        handleSubmit = (event)=>{
            // 利用事件对象阻止默认事件,在这里是阻止了表单的提交
            event.preventDefault();
            const {username,password} = this.state;
            alert(`用户名为:${username},输入的密码为:${password}`)
         
        }
        
        saveFormData(dataType,event){
           this.setState({
               [dataType]:event.target.value
           })
        }
        render(){
            return(
                <form onSubmit = {this.handleSubmit}>
                    用户名:<input type="text" name='username' onChange = {event=>this.saveFormData('username',event)} />
                    密码:<input type="password" name='password' onChange = {event=>this.saveFormData('password',event)}/>
                    <button>登录</button>
                </form>
            )
        }
    }
    // 渲染组件到页面中
    ReactDOM.render(<Login/>,document.getElementById('test'))
    </script>
</body>
</html>
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值