React学习笔记

一、几个概念

库和框架
  • 库(library):小而巧,可以很方便的从一个库切换到另一个库,但是代码几乎不会改变。
  • 框架(framework):大而全,框架提供了一整套完整的解决方案,在项目中间想要切换框架是困难的
模块化和组件化
  • 模块化:是从代码的角度进行分析,把可复用的代码抽离为单个模块,便于项目的维护和开发
  • 组件化:从UI界面的角度进行分析,把可复用的UI元素,抽离为单独的组件

二、React的基础概念

1、虚拟DOM
  • DOM的本质:浏览器中的概念,用JS对象来表示页面上的元素,并提供了操作相应DOM对象的API
  • 虚拟DOM:是框架的概念,是程序员用JS对象来模拟页面上的DOM和DOM嵌套
  • 虚拟DOM的目的:为了实现页面中DOM元素的高效更新。
2、Diff 算法
  • tree diff: 新旧两棵DOM树,逐层对比的过程。当整个DOM逐层对比完毕,则所需要被按需更新的元素,必然能够找到
  • component diff :在进行tree diff的时候,每一层中,组件级别的对比。
    • 对比前后,组件类型相同,则认为此组件暂时不需要被更新
    • 对比前后,组件类型不同,则需要移除旧的组件,创建新的组件,并追加到页面上。
  • element diff:在进行组件对比的时候,如果两组件类型相同,则需要进行元素级别的对比。

三、使用webpack4.x搭建项目

  1. npm init -y 初始化
  2. 创建src源代码目录和dist目录
  3. 安装:npm i webpack -D npm i webpack-cli -D
  4. 在webpack.config.js中配置mode
      module.exports={
           mode:‘development’,//development 开发环境,
          //在webpack 4.x中有一个很大的特性 约定大于配置
       }
    
  5. 约定大于配置,打包入口路径:在src下的index.js,出口文件:dist下的main.js
  6. 配置实时编译 npm i webpack-dev-server -D后在package.json的scripts下"dev":"webpack-dev-server"--->npm run dev--->引入的js文件在根目录
  7. 配置html-webpack-plugin

四、使用React渲染最基本的虚拟DOM到页面上

1、下载、引入
  • 下载 npm i react react-dom
  • 在index.js中引入:import React from ‘react’ import ReactDom from 'react-dom'
2、创建虚拟的dom元素
  • const myh1 = React.createElement(‘h1’,null,‘这是一个h1’)
    • 参数1:创建的元素的类型,字符串,表示元素的名称
    • 参数2:一个对象或者null,表示当前dom元素的属性
    • 参数3:子节点(包括 其他 虚拟DOM 或者文本的子节点)
    • 参数n:其他子节点
3、使用ReactDom把虚拟DOM渲染到页面上
  • ReactDom.render(myh1,document.getElementById("app"))
    • 参数1:要渲染的虚拟DOM元素
    • 参数2:指定页面上的一个容器
4、例子
   import React from 'react'
   import ReactDom from 'react-dom'
   var myDiv = React.createElement('h1',null,'这是react');
   ReactDom.render(myDiv,document.getElementById('box'))

五、JSX介绍和使用

  • 在JS中默认不能写入html标记,否则会打包失败,可以使用babel来转换这些js标签,在js中混入类似于html的语法叫做JSX,符合xml规范
  • JSX语法的本质:在运行的时候被转换成React.createElement形式来执行
1、启用JSX
  • 安装babel插件
    • npm i babel-core babel-loader babel-plugin-transform-runtime -D
    • npm i babel-preset-env babel-preset-stage-0 -D
  • 安装能够识别转换JSX语法的包
    • npm i babel-preset-react -D
  • 在webpack.config.js中添加babel-loader
    module://所有第三方 模块的配置规则
    {
       rules:[//第三方匹配规则
           { test:/\.js|jsx$/,use:'babel-loader' , exclude:/mode_modules/}
        ]
     }
    
  • 添加.babelrc配置文件
    { 
       "presets" : ["env","stage-0","react"],
       "plugins" : ["transform-runtime"]
    }
    
2、在JSX中书写JS代码注意点
  • 变量使用{a}插入
  • 标签中的属性值:title={}
  • 在JSX中,写注释{//}(需要换行)、{/* 这是注释 */},
  • 为JSX中得元素添加class类名需要使用className来替代class,htmlFor替代for
  • 在JSX语法中,标签必须成对出现,单标签则必须自闭和。
  • 在JSX创建DOM的时候,所有的节点,必须有唯一的根元素进行包裹
  • 在JSX中不能为style设置字符串的值,应该写style = {{color:‘red’}},行内样式,如果是字符串类型就需要引号包裹。
let message = '这是js中的参数'
let nameStr = ['张三','李四','王五','赵六']
let nameArr = []
  nameStr.forEach((item)=>{
        let nameItem = 
{item }
nameArr.push(nameItem) }) { //什么时候使用{}:当在JSX控制的区域内,写JS表达式就需要 } ReactDom.render(
{ message }
{nameArr}
{nameStr.map( item =>
{item}
) }//方法二
,document.getElementById('app'))

六、组件

1、使用构造函数来创建组件:
  • 创建组件

    // 组件名称的首字母需要大写
      function Hello (props) {
         //在构造函数中接收外界传入的参数,传入的prop是只读的
           console.log( props )//{ name : '张三',  age : 14}
          //如果return null表示组件是空的什么都不渲染
         //组件必须ruturn,必须返回一个合法的 JSX 虚拟DOM元素
           return 
    这是Hello组件
    } //还可以使用解构赋值来传递对象 var dog={ name:‘旺财’, age:12 }
  • 分离组件

      //文件名:Hello.jsx
       import React from 'react'
            export default function Hello(props){
            return 
    {props.name}
    } //在index.js中导入使用,默认不做单独配置的话,不能省略.jsx后缀 import Hello from '路径/Hello.jsx'
    • 使用 Person.defaultProps = { sex:'男' } 设置传递参数的默认值
    • 使用 Person.propTypes = { name:PropTypes.string.isRequired }设置属性的类型和必要性
    • 配置,省略后缀名,在webpack.config.js中添加
      resolve:{ 
          extension:['.js' , '.jsx' , '.jsx' ],//表示这几个文件名后缀可以省略
          //配置webpack设置项目根目录
          alias:{//表示别名
             '@':path.join(__dirname,'./src')//这样@就表示项目根目录中src这一层路径
          }
      }
      
2、基于关键字class创建组件
  • 静态属性和实例属性
    • 静态属性用static修饰,用类名访问
  • 静态方法和实例方法
  • 在class{}中只能写构造器、静态方法、静态属性、实例方法
  • class关键词内部,还是用原来的配方实现,所以class称为语法糖
  • 继承时,子类constructor(){需要super() }
     class Movie extends React.Component{//必须继承Component
           render(){//必须有render函数
               return 
    我是一个组件
    //必须返回合法的 JSX虚拟DOM结构 } } ReactDom.render(
    , document.getElementById('app'))
  • 使用this.props.参数名获取参数
4、两种创建组件方式的区别
  • 使用class关键字创建的组件,有自己的私有数据和生命周期数;用function创建的组件,只有props。
  • 构造函数创建出来的组件叫做“无状态组件”,用class创建的组件“有状态组件”
  • 两种方式之间的区别是:有无state属性和有无生命周期
5、组件中propsstate/data之间的区别
  • props中的数据都是外界传递过来的;
  • state/data中的数据,都是组件私有的(通过Ajax获取回来的数据,一般都是私有数据)
  • props中的数据是只读的,不能重新赋值,state/data中数据可读可写
6、在组件内使用内联样式style
  • 在JSX中如果想写行内样式,不能为style设置字符串的值,而是应该写成style={ { color:‘red’ } }
  • 在行内样式中,如果是数值类型的样式则不用引号包裹,如果是字符串类型的样式值,必须用引号包裹。
  • 可以封装成一个样式对象通过import 引入
  • 引入css,需要配置。直接导入css样式表,默认是在全局上整个项目都生效。
7、为css启用modules
  • 在webpack.config.js中配置css时
  • rules:[ { test: /\.css$/, use:['style-loader','css-loader?modules']} ], //modules为普通的css启用模块化
    • 启用模块化后,不会在全局生效
  • css模块化,只针对 类选择器 和id选择器生效,不会将标签选择器模块化
  • 使用localIdentName自定义生成类名格式,可选参数有:
    • [path] 表示样式表 相对于项目根目录 所在的路径
    • [name] 表示样式表 文件名称
    • [local] 表示样式表 类名定义名称
    • [hash:length] 表示32位的hash值
    • 例子:
    //在webpack.config.js中
    rules:[  { 
      test: /\.css$/, use:['style-loader','css-loader?modules&localIdentName=[path][name]']
    } ]
    
    // 在cmtlist.jsx中
    import cmtStyle from ‘@/css/cmtlist.style’
    

    标题

  • 被:local()包裹起来的类名,会被模块化,默认所有的类名和id都被模块化。
  • :global()包裹起来的类名,不会被模块化,而是全局生效
七、在项目中启用模块化并同时使用bootstrap
  • 打包处理 字体文件的loader:{test:/\.ttf|woff|woff2|eot|svg$/,use:'url-loader'}
  • 如果在引用某个包时,这个包被安装到了node_modules目录中,则可以省略node_modules这一层目录,直街以包名开始引入自己的 模块或样式表
  • 自己规定:
    1. 把自己的样式表,定义为.scss文件或 .less文件。
    2. 第三方的 样式表 还是以.css结尾
    3. 我们只需要为自己的.scss文件或 .less文件,启用模块化
  • 安装能够解析scss文件的loader: 运行npm i sass-loader node-sass -D
     //css文件无需模块化
     { test: /\.css$/, use:[ 'style-loader','css-loader','sass-loader']},
     //scss启用模块化 
     { test: /\.scss$/, use:[ 'style-loader','css-loader?modules','sass-loader']}  
    

八、React中绑定事件

  • onClick = { function }

  • 在方法中修改state中的值,使用this.setState({msg:})

    • setState的注意点:
      • setState只会把对应的state状态更新,而不会覆盖其他的state状态
      • setState方法是异步的,调用完需要马上用到新值需要使用 this.setState({},callback)
  • 注释://#region 开始注释 //#endregion

  • 获取文本框的值

    • e.target.value
    • this.refs.txt.value
      class BtnEvent extends React.Component{
        constructor(){
            super()
            this.state = { msg:'这是测试事件的组件'  }
        }
        render(){
            return 

    {this.state.msg}

    {/* 为文本框绑定value值以后,要么同时提供一个readOnly,要么提供一个onChange处理函数**/} this.changeInput(e)} ref='txt'/>
    } setDate=(arg1,arg2)=>{ this.setState({ msg: arg1+arg2 },()=>{ console.log(this.state.msg) }) } changeInput = (e)=>{ //获取文本框的值有两种方法, this.setState({msg:e.target.value})//一:通过时间参数e获取 console.log(this.refs.txt.value) //二:this.refs.txt..value } }

九、组件的生命周期

  • 生命周期的概念:每个组件的实例从创建、运行到销毁,在这过程中,会促发一些事件,这些事件就叫做组件的生命周期函数
  • 组件的三个生命周期状态:
    • Mount:插入真实的DOM
    • Update:被重新渲染
    • Unmount:被移出真实的DOM
  • 组件的创建阶段:只执行一次
    • componentWillMount():将要插入回调
    • render():用域插入虚拟DOM回调
    • componentDidMount():已经插入回调
  • 组件的运行阶段、更新
    • componentWillReceiveProps():
    • shouldComponentUpdate()
    • componentWillUpdate():将要更新
    • render():更新(重新渲染)
    • componentDidUpdate():已经更新
  • 组件的销毁阶段:只执行一次
    • componentWillUnmount():组件将要被移除

你可能感兴趣的:(React学习笔记)