最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React学习笔记(1)

    正文概述 掘金(三个小色素点)   2020-12-08   583

    1. 创建react项目

    • 安装 npx create-react-app my_app
    • 运行 npm start

    2. 环境介绍

    • node_modules 依赖包
    • public 入口文件
    • src 源代码文件
    • package.json 配置文件

    3. React和Vue文件结构

    • React和Vue的文件结构是不一样的
    • Vue: 结构是( 模板 —— 逻辑 —— 样式 )
    <template>
    	<view>
    		模板
    	</view>
    </template>
    <script>
    	export default {
    		data() {
    			return {info:"逻辑"}
    		}
    	}
    </script>
    <style lang="scss" scoped>
    	view{
    		样式
        }
    </style>
    
    • React:JSX文件中是逻辑和模板,React需要另外引入样式
    import React, { Component } from 'react';
    import "./myStyle.css";
    export default class test extends Component {
        render() {
            return (
                <div>
                </div>
            );
        }
    }
    

    4. React —— JSX语法

    • 在遍历渲染的时候尤其明细jsx的语法
     <ul>
          {/* jsx中是遇到花括号就识别为js语法, 遇到尖括号就识别为html语法,
              在遍历完成后返回一个标签,就会解析为html来渲染*/}
          {
              this.props.myNav.map((e,i)=>{
              return <li key={i}>{e}</li>
              })
          }
      </ul>
    
    • jsx语法中是没办法用html的注释的,要用注释只能是 {/* */}花括号把它套起来,jsx解析到花括号就会自动解析成js语法

    5. React —— 组件

    super小知识

    react的组件名不能小写开头,首字母需要大写,其他的随意。否则会警告,且不显示

    Warning: The tag <setStateDome> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
    
    • 组件的引入方式也和vue那些差不多,使用ES6的import引入,并且引入的组件也是以标签的形式展现。
    import Nav from './Nav/Nav';
    
    //用类的形式创建组件,还有一种是hook形式
    export default class App extends React.Component{
        //render渲染函数
        render(){
            const nav1 = ['首页','学习','导航']
            const nav2 = ['吃饭','睡觉','大泡泡']
            const { count } = this.state //这里使用解构赋值,需要什么数据,引入什么数据即可
            return ( 
                <>
                	<div>欢迎使用组件</div>
                        /*通过定义属性得方式,把数据传输给子组件,
                        因为是再函数体内,直接输入变量命即可,
                        自定义属性是可以传输任何类型得数据得*/
                    <Nav myNav={nav1}  />
                    <Nav myNav={nav2} /> */}
                    <State />
                </>
            )
        }
        
    } 
    

    6. React中使用组件局部样式

    • react不像vue在样式加上scoped就可以让样式不污染全局
    • react的解决方法是,引入一个 *.module.css 后缀的文件
      • 之前类选择器是.main, 使用时只需要这样写className="header"。但是在组件局部样式里面,需要在要指定样式的元素上写className={styles.header}。
    // js
    import React, { Component } from 'react';
    import "./myStyle.css";				//之前直接导入的方式
    import myStyle from "./myStyle.module.css";    //命名的方式 引用样式就不会污染到环境
    export default class componentName extends Component {
        render() {
            return (
                <>
                    <div className={myStyle.main}></div>
                </>   
            )
        }
    }
    // ./myStyle.module.css
    .main{
        background-color: pink;
        width: 150px;
        height: 150px;
    }
    

    React学习笔记(1)

    React学习笔记(1)

    7. 组件通讯方式

    7.1 ,props 是父组件与子组件交互的唯一方式
    • props的特性是不能修改的,只能接收、传输数据!
    ## ./Nav/Nav.jsx
    export default class Nav extends React.Component{
        render(){
            console.log(this.props.title)
            //接收数据得时候需要在props中获取
            return (
                <div>
                    <h3>{this.props.title}</h3>
                    <ul>
                        {/*
                            jsx中是遇到花括号就识别为js语法,
                            遇到尖括号就识别为html语法,在遍历完成后
                            返回一个标签,就会解析为html来渲染
                        */}
                        {
                            this.props.myNav.map((e,i)=>{
                            return <li key={i}>{e}</li>
                            })
                        }
                    </ul>
                </div>
            )
        }
    }
    
    7.2 父组件向子组件传值
    • 在使用子组件的标签中,直接加入使用一个自定义属性就可以传递数据给子组件,子组件中直接 this.props.myData 用props可以直接获取传输过来的数据
    // 父组件
     <myChild myData={"父组件传递的数据"}/>
    // 子组件
     render() {
          console.log(this.props.myData)
      }
    
    • 子组件向父组件传递数据,通过子组件调用父组件的方式,并且可以将数据当参数返回
    // 父组件
     render() {
          return (
              <div className="main">
                   {/* <Login/> */}
                  <myChild callback={this.childValue}/>
              </div>
          )
      }
      childValue = (data) =>{
          console.log('app',data)
          this.setState({
              dataList:data
          })
      }
     
    // 子组件
      handleClick(){
          this.props.callback(this.state.count)
      }
    
    7.3 表单控件
    • react使用控件的时候需要添加上 onChange 绑定个方法
    constructor(){
        super();
        this.state={
            value:''
        }
    }
    onChangeValue=(e)=>{
        this.setState({
            value:e.target.value
        })
    }
    render(){
    	return <input type="text" value={this.state.value} onChange={this.onChangeValue}/>
    }
    
    • 非控制组件

    Refs 可以操作DOM上的节点或者render方法中创建的元素节点,

    • ref适用于这几种情况
      • 管理焦点,文本选择或媒体播放
      • 触发强制动画
      • 集成第三方DOM库
    • refs需要使用React.createRefs()创建,并通过ref属性附加到React元素中,勿过度使用Refs。

    特殊情况才去操作DOM

    constructor(){
        super();
        this.input = React.createRef();//
    }
    componentDidMount() {
        this.input.current.style.color='pink'//修改DOM节点的样式
    }
    handleSubmit=(e)=>{
        alert('测试看看'+this.input.current.value) //获取DOM节点的值
        e.preventDefault();//取消触发默认行为
    }
    render() {
        return (
           <input type="text" ref={this.input}/>
           <input type="submit" value="submit" onClick={this.handleSubmit}/>
        )
    }
     
    

    8. 事件处理

    8.1 this问题
    • react中的函数方法和vue中使用的不一样,react中方法的this指向的undefined,这不是React的原因,这是JavaScript中本来就有的。如果你传递一个函数名给一个变量,然后通过在变量后加括号()来调用这个方法,此时方法内部的this的指向就会丢失。
      • 可以使用箭头函数,让该函数访问外部上下文
      • 可以使用bind(this)把外部的this绑定给该函数
      
       
      class componentName extends Component {
        constructor(props){
            super(props);
            //在构造函数中bind
            this.handleClick.bind(this)
        }
        //使用箭头函数,让该函数访问外部上下文
        decrement=()=>{
            this.setState({
                count:this.state.count-=1
            })
            console.log(this);
        }
        //在调用的时候使用bind绑定this
        handleClick(){
            console.log(this);
        }
        render() {
            return (
                <>     
                    <div className={myStyle.main} onClick={this.handleClick.bind(this)}>在调用的时候使用bind绑定this</div>
                </>   
            )
        }
      }
      
      
    // 这个函数是有自己的作用域的,所以需要给他bind()一下,或者使用箭头函数修改this指向
       increment(){
            this.setState({
                // 由于这里的count是属于调用state中的count所以必须加上this.state
                count:this.state.count+=1
            })
            console.log(this);
       }
       decrement=()=>{
            this.setState({
                count:this.state.count-=1
            })
            console.log(this);
       }
        render() {
            return (
                <div>
                    <h3>组件的state</h3>
                    <div>这是state渲染的---》{this.state.count}</div>
                    <button onClick={this.increment.bind(this)}>增加</button>
                    <button onClick={ this.decrement }>减少</button>
                </div>
            );
        }
    
    8.2 条件渲染
    • 条件渲染

      • react不像vue的写法,在标签中添加一个v-if的属性就可以使用判断。react的用法是类似js一样的。if...else和三元运算符
       render() {
      const {dataList} = this.state
      //条件渲染,if ... else模式
      let myDiv = ''
      if (true) {
      //赋值给变量的标签内容都可以在 render函数的渲染的时候,以html方式依次渲染出来
        myDiv = (
              <div>
                测试 上
                <p>1111</p>
                <span>2222</span>
                <img src="http://pic1.win4000.com/wallpaper/2020-10-21/5f8f95f2a49e2.jpg" />
              </div>
          )
      }else{
        myDiv = <div>测试 下</div>
      }
      return (
        <div>
          <ul>
            {myDiv} // 变量判断渲染出来的元素
            {
              // 条件渲染三元运算(中间利用了循环遍历)
              dataList.length ?
                dataList.map((item,index)=>{
                  return <li key={index}>{item.title}</li>
                  })
              :
                <div>当前没有数据</div>
            }
          </ul>
        </div>
      )
      }
      
    • 循环遍历

      • react的循环遍历渲染和vue小程序那些是有差异的,不像后者只需协商v-for这类的属性名就可以使用。由于react使用的是jsx语法,所以它的遍历渲染是类似js的循环遍历一样的
      this.state= {
          myList:[
              {
                  name:'ime',
                  age:10,
                  sex:"男"
                  ,jobs:['111','222','333']
              }
          ]
      }
     <ul>
          {
              this.state.myList.map((element,index)=>{
                  return(
                      <li key={index}>
                          <span>{element.name}</span>
                          <span>{element.age}</span>
                          <span>{element.sex}</span>
                          <span>{
                              element.jobs.map((e,i)=>{
                                  return <p style={{color:'pink'}}>e</p>
                              })
                          }</span>
                      </li>
                  )
              })
          }
      </ul>
    
    

    9. State

    • 这个和微信小程序中的data或Vue的data差不多,主要是存数据,数据交互。存数据的方式和小程序很类似。
    • React的this.setState 和小程序中的this.setData 是很类似的,接触过小程序的对这个存储方式并不陌生,反而和vue的直接赋值不一样。
    9.1 setState更新是同步还是异步
    • setState会引起视图的重绘
    • 在可控的情况下是异步,非可控的情况下是同步
    如果直接使用,数据还是原来的值,因为是异步的。至于为什么设计为异步,因为异步操作也是有好处的。
            1. 可以显著的提升性能
                如果每次调用setState都进行一次更新的话,render函数是会被频繁调用的,界面不断的被重新渲染,
                这样会消耗大量的资源,导致效率变低。最好就是一次性获取多个数据,然后再批量的更新
            2. 如果同步更新state,但是还没有调用render函数,那么state和props不能保持同步state和props不能保持一致性,
                会在开发的过程中产很多问题
    
            改变DOM同时又要获取最新的值
            1. setState有一个回调函数,在回调函数中可以取到更新后的最新值
                changeNumber(){
                    this.setState({
                        message:'哈哈'
                    },()=>{
                        console.log(this.state.message)
                    })
                }
            2. 通过componentDidUpdate函数,组件的更新会触发它,此时就是同步的新数据
                componentDidUpdate(prevProps, prevState) {
                    console.log(this.state.message)
                }
    
            3. 使用async await也是可以改为同步
                async hanlerAdd(){
                    await this.setState({
                        count:this.state.count+=1
                    })
                    console.log(this.state.count);
                }
            
            4. 使用原生DOM操作,默认也是同步
                <button id="btn">减</button>
                hanlerAdd(){
                    document.querySelector('#btn').addEventListener("click",()=>{
                    this.setState({
                        message:'哈哈'
                    })
                    console.log(this.state.message)
                })
    

    10. React生命周期函数

    React学习笔记(1) 函数列表:

    • componentWillMount

      • 组件初始化时只调用,以后组件更新不调用,整个生命周期只调用一次,此时可以修改state。
      • 和小程序、vue、uniapp的 onLoad 差不多
    • render

      • react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行。此时就不能更改state了。
    • componentDidMount

      • 组件渲染之后调用,只调用一次。可以在此请求数据
    • componentWillReceiveProps

      • 组件初始化时不调用,组件接受新的props时调用。
    • shouldComponentUpdate

      • 数据在改变之前执行(state,props)
      • react性能优化非常重要的一环。组件接受新的state或者props时调用,我们可以设置在此对比前后两个props和state是否相同,如果相同则返回false阻止更新,因为相同的属性状态一定会生成相同的dom树,这样就不需要创造新的dom树和旧的dom树进行diff算法对比,节省大量性能,尤其是在dom结构复杂的时候
    • componentWillUpdata(nextProps, nextState)

      • 组件初始化时不调用,只有在组件将要更新时才调用,此时可以修改state

    11.PropsTypes 类型检测

    • 类似于ts的类型检测,使程序更加健壮。类型检测的好处在于,随着程序越来越大,可以通过它捕获大量的错误。
    • PropsTypes给props做类型检测
    import React, { Component } from 'react';
    import PropsType from 'prop-types';
    export default class PropsTypeDemo extends Component {
        render() {
            return (
                <div>
                    {this.props.title}
                </div>
            );
        }
    }
    PropsTypeDemo.propTypes = {
        title:PropsType.bool
    }
    // 如果传递的数据不对,则报错  Failed prop type:
    
    • props types提供了几种类型的校验
    // 声明属性为js原生类型,这些属性都是可选的
     optionalArray: PropTypes.array,
     optionalBool: PropTypes.bool,
     optionalFunc: PropTypes.func,
     optionalNumber: PropTypes.number,
     optionalObject: PropTypes.object,
     optionalString: PropTypes.string,
     optionalSymbol: PropTypes.symbol,
    
     //任何可被渲染的元素,包含数字、字符串、元素和数组
     optionalNode: PropsTypes.node,
     
     // 一个React元素
     optionalElement: PropsTypes.element,
     
     //一个React元素类型 
     optionalElementType:PropsTypes.elementType,
     
     //一个对象可以是几种类型中的任意一个类型
     optionalUnion: PropsTypes.oneOfType([
     	PropsTypes.string,
        PropsTypes.number,
        PropsTypes.instanceOf(Message)
     ])
     
     //任意类型的必需数据
     requiredAny: PropsTypes.any.isRequired,
     
     //自定义验证器,失败时返回Error对象。但是在 console.warn和抛出异常中是不可用的,onOfType 不会生效
     customProp:function(props, propName, componentName){
     	if(!/matchme/.test(props[propName])){
        	return new Error(
            	`验证信息有误`
            )
        }
     }
     
     ### 更多的用法可以查看官方文档
    

    12. 路由

    • history 模式
      • window 的 history 提供了对浏览器历史记录的访问功能,并且它暴露了一些方法和属性,让你在历史记录中自由的前进和后退,并且在 H5 中还可以操作历史记录中的数据。
      history.back() ;	// 在历史记录是后退
      history.forward();      // 在历史记录中前进
      history.go(-1);	// 移动到指定的历史记录点
      
    • hash 模式
      • hash的改变,不会导致浏览器的刷新

    13. 网络请求,Fecth

    • fetch和axios都是基于promise设计的,可以先把promise的知识学一学有助于对这个库的理解更加透彻。
    • fetch写起来代码会更加简洁(这里是使用了es6的箭头函数以及 promise的 .then 来写的)
    componentDidMount() {
    // GET请求
    fetch("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php").then(res => res.json())
      .then(data =>{
        if( data.success ){ //这里是后端返回的成功码
          console.log(data);
        }
      }).catch(err => console.log('错误信息',err))
     
     /* POST请求
          * Ajax的参数是对象键值对的
          * Fetch的body 是字符串类型
          	* "user_id=123123&password=123123&verification_code=123123"
            Fetch识别的是这样子的类型请求参数
         * import qs from "querystring"; 
         	* 引入nodeJs的对象转换字符串方法
    */
       fetch("http://iwenwiki.com/api/blueberrypai/login.php",{
          method:"POST",
          body: qs.stringify({ // 引入了nodeJs的对象转字符串方法 qs.stringify
            user_id:123123,
            password:123123,
            verification_code:123123
          }),
          headers:{
            "Content-Type":'application/x-www-form-urlencoded',
            "Accept":"application/json,text/plain,*/*"
          }
       }).then(res=>{res.json()})
       .then(data=>{
        console.log(data);
       }).catch(err => console.log(err))
      }
     }
    
    • 网络请求的过程中是会出现跨域问题的,端口不同就会出现跨域问题,一般这种问题可以让后端去解决。不过前端也是有解决的方法。

      • 步骤一 npm install http-proxy-middleware
      • 步骤二 npm run eject
      • 步骤三 src下创建一个 setupProxy.js文件
      //0.X 版本的引入这个
      //const proxy = require('http-proxy-middleware');
      //1.X 版本的引入这个
      const { createProxyMiddleware } = require("http-proxy-middleware");
      module.exports = function(app) {
        app.use(
          createProxyMiddleware("/api", {
            target: "http://localhost:3000",
            changeOrigin: true
          })
        );
      };
      
      • 步骤四 start.js里面做一下配置
      // 在scripts文件夹里面的start.js 搜索 devServer
      const serverConfig = createDevServerConfig(
        proxyConfig,
        urls.lanUrlForConfig
      );
      const devServer = new WebpackDevServer(compiler, serverConfig);
      //在它下面添加上即可
      require('../src/setupProxy')(devServer);//文件路径按自己的来
      

    下载网 » React学习笔记(1)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元