react传参相关记录

一级目录

二级目录

三级目录

一、原理相关:

1、关于render渲染两次的原理

https://www.cnblogs.com/chaoyuehedy/p/9638848.html

二、问题:

1. fetch请求

let getFileTypesUrl = `${context.contextPath}/projectfile/getAllFileTypes?p_no=` + this.state.projectNo;
//调用方法
this.getFileTypes(getFileTypesUrl)



getFileTypes(url) {
        fetch(url,
            {
                method: "GET"
            })
    		//后台请求的响应结果 data:请求到的数据,类似于ajax
            .then((response) => response.json())
            .then((data) => {
                let list = [];
                if (data !== null && data !== undefined) {
                    data.forEach((item, index, arr) => {
                        let obj = {value: item, text: item};
                        list.push(obj);
                    });
                    this.state.fileTypes = list;
                }
            })
    }

同步:
homePage.js
法一:回调

import {ewdUrl,fnNewToken, fnNewToken2} from "./util/util";
getNewToken2() {
   let that = this
    fnNewToken2((newToken)=>{
      console.log("myfunc",newToken)
      that.setState({
      token: Boolean(newToken) ? newToken : localStorage.getItem("jwtToken")
    })
  });
  // console.log('newToken===', newToken)
}

法二:

async getNewToken() {
  let newToken = await fnNewToken();
  console.log('newToken===', newToken)
  this.setState({
    token: Boolean(newToken) ? newToken : localStorage.getItem("jwtToken")
  })
}

util.js
法一:回调

export let fnNewToken2 = function (myfunc) {
    let newToken = '';
    let tokenURL = casUrl + "/cas/jwt/token";
    fetch(tokenURL, {
        method: 'GET',
        credentials: 'include',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded;'
        }
    }).then(resp => resp.json()).then(resp => {
        if (resp) {
            if (resp.status === true) {
                newToken = resp.jwtToken;
                if(myfunc){
                    console.log("util token", newToken)
                    localStorage.removeItem("jwtToken");
                    localStorage.setItem("jwtToken", newToken)
                    myfunc(newToken)
                }
            } else {
                console.log('token校验失败')
            }
        }
    })
};

法二:

export let fnNewToken = async function () {
    let tokenURL = casUrl + "/cas/jwt/token";
    let response = await fetch(tokenURL, {
        method: 'GET',
        credentials: 'include',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded;'
        }
    })
    let data = await response.json();
    console.log("=====data====",data)
    if(Boolean(data.status) && data.status === true){
        localStorage.removeItem("jwtToken");
        localStorage.setItem("jwtToken",data.jwtToken)
        localStorage.setItem("refreshToken",data.jwtToken)
        return data.jwtToken;
    } else{
        console.log("token校验失败!")
        return null;
    }
};

2、方法

onClick: (item, events) => {    
    let previewUrl = `${context.contextPath}/projectfile/getFileInfo?fileId=` +rowData.file_id;    
    this.showModal.call(this,previewUrl);
}

showModal 用call()方法,不用在constructor声明 this.showModal = this.showModal.bind() 直接写该方法内容即可。
该处 使用this.showModal.bind(this)这样的形式不能进入到该方法。

3、返回

  1. 返回上一个url
    document.referrer: referrer属性返回载入当前文档的来源文档的URL
    window.location.replace(document.referrer);
    window.location.reload(document.referrer);
    Location 对象方法:
    assign() 载入一个新的文档
    reload() 重新载入当前文档
    replace() 用新的文档替换当前文档

  2. 新打开浏览器页签:
    window.open(url, ‘_blank’).location;

  3. 跳转,去请求后台
    window.location = ${context.contextPath}/projectpage/index?p_no=+p_no;

  4. js存储对象
    JavaScript 存储对象
    Web 存储 API 提供了 sessionStorage (会话存储) 和 localStorage(本地存储)两个存储对象来对网页的数据进行添加、删除、修改、查询操作。

localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去除。

sessionStorage 用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据。

存储对象方法
方法							描述
key(n)						返回存储对象中第 n 个键的名称
getItem(keyname)			返回指定键的值
setItem(keyname, value)		添加键和值,如果对应的值存在,则更新该键对应的值。
removeItem(keyname)			移除键
clear()						清除存储对象中所有的键

window.localStorage		在浏览器中存储 key/value 对。 没有过期时间。
window.sessionStorage	在浏览器中存储 key/value 对。 在关闭窗口或标签页之后将会删除这些数据。

4、sessionStorage和localStorage和cookie

sessionStorage

componentDidMount(){
	 this.setIndex();
}
 setIndex(){
        //判断是否存在
        // if(!window.sessionStorage) {
            if (sessionStorage.getItem("index") != null) {
                let indexData = sessionStorage.getItem("index");

				//componentDidMount不能用setState ,setState 是异步的 ,想立马看到state修改后的值,这就用到了setState的回调
                this.setState({index: indexData}, () => {
                    console.log('index', this.state.index);
                });
            }
            else {
                this.setState({index: 0});
            }
        // }
    }

存:sessionStorage.setItem(“index”,index );
localStorage.setItem(“jwtToken”,jwtToken)
取:sessionStorage.getItem(“index”)
localStorage.getItem(“jwtToken”) 移除:
localStorage.removeItem(“jwtToken”)

使用cookie存储用户信息:
session/cookie 是用于存储用户相关信息的数据存储形式
session存储在服务器保存的是对象,而cookie存储在浏览器本地保存的是字符串
由于session是存储在服务器,会占用服务器资源,一般来说小型项目使用cookie的较多

1.下载cookie相关的包
npm install react-cookies --save

2.cookie知识储备
引用
import cookie from 'react-cookies'

3、存; 设置cookie,第三个参数的意思是所有页面都能用这个cookie
cookie.save(key,value,{path:"/"})
4、取
cookie.load('userId')
5、删
cookie.remove('userId')
6、设置失效
let inFifteenMinutes = new Date(new Date().getTime() + 24 * 3600 * 1000);//一天
cookie.save('userId', "123",{ expires: inFifteenMinutes });

根据以上存取cookie的格式,可以写出cookie.js

import cookie from 'react-cookies'


获取当前用户cookie
export const loginUser = () => {
  return cookie.load('userInfo')
}


 用户登录,保存cookie
export const onLogin = (user) => {
  cookie.save('userInfo', user, { path: '/' })
}


用户登出,删除cookie
export const logout = () => {
  cookie.remove('userInfo')
  window.location.href = '/Login'
}

3、react页面调用

以学生管理系统为例,未登录(无cookie时)pathname为’/‘时,跳转到Login进行登录,登录后跳转到对应权限页面。已登录(有cookie存储时)pathname为’/'时,跳转到当前用户对应的权限主页面

import React, { Component } from 'react'
import { Router, Route, Switch } from 'react-router-dom'
import { createBrowserHistory } from 'history'
import { loginUser } from './cooike' // 引入
import {
  StudentLayout, TeacherLayout, AdminLayout, Login,
} from './pages' // 导入页面
import NotFound from './components/Common/NotFound'
import Loading from './components/Common/Loading'

const browserHistory = createBrowserHistory() // 路由分发

class BasicRoute extends Component {
  render () {
    const userInfo = loginUser()
    if (userInfo && window.location.pathname === '/') {
      if (userInfo.accountRole === 0) {
        window.location.href = '/Admin'
      } else if (userInfo.accountRole === 1) {
        window.location.href = '/Teacher'
      } else if (userInfo.accountRole === 2) {
        window.location.href = '/Student'
      }
    }
    return (
      <Router history={browserHistory}>
        <Switch>
          {
            !loginUser()
              ? <Route exact path="/Login" component={Login} />
              : (
                <>
                <Route path="/Student" component={StudentLayout} />
                <Route path="/Teacher" component={TeacherLayout} />
                <Route path="/Admin" component={AdminLayout} />
                </>
              )
          }
          <Route exact path="/" component={Loading} />
          <Route exact component={NotFound} />
        </Switch>
      </Router>
    )
  }
}

export default BasicRoute

react-cookie官网实例: https://www.npmjs.com/package/react-cookies

补充:

用户登出,删除cookie

export const logout = () => {
  cookie.remove('userInfo')
  window.location.href = '/Login'
}

如果未在cookie.remove()方法中指定path,那么并不会完全登出当前账号,比如在/Admin/Personal/Add路径下点击退出按钮,并不会如预期登出,解决这个问题的办法就是,在cookie.remove()方法中设定path

用户登出,删除cookie

export const logout = () => {
  cookie.remove('userInfo', { path: '/' })
  window.location.href = '/Login'
}

就可以解决cookie并未清除的问题了

5、componentWillMount和componentDidMount的区别

关于react生命周期 https://www.runoob.com/react/react-component-life-cycle.html

组件的生命周期可分成三个状态:

  • Mounting:已插入真实 DOM
  • Updating:正在被重新渲染
  • Unmounting:已移出真实 DOM

生命周期的方法有:

componentWillMount 在渲染前调用,在客户端也在服务端。 componentDidMount :
在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。
如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout,
setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。 componentWillReceiveProps
在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。 shouldComponentUpdate
返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。可以在你确认不需要更新组件时使用。
componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。 componentWillUnmount在组件从
DOM 中移除之前立刻被调用。

6、react setState理解

https://segmentfault.com/a/1190000015463599?utm_source=tag-newest

7、react中 this.setState({index:1}) 和 this.state.index=1 的区别

1)this.state通常是用来初始化state的,this.setstate是用来修改state值的。如果你初始化了state之后再使用this.state,之前的state会被覆盖掉,如果使用this.setState,只会替换掉相应的state值。
2)this.setState({})会触发render方法,重新渲染界面。而this.state.xxx=’’ 不会重新加载UI。

3)this.setState({})是异步的。

https://blog.csdn.net/weixin_43199050/article/details/93098980

8、headers添加token 报错

解决方法:(原因不太清楚)

// props改变时 更新state
componentWillUpdate(nextProps, nextState, nextContext) {
  // 先比较值是否一样
  if (this.state.pass !== nextProps.pass) {
    this.setState({
      pass: nextProps.pass
    })
  }
}

9、父子组件传参问题

父组件给子组件传参:

// 父组件中 SpotInspector为子组件名

  <SpotInspector
          status={statusMap[indexArr[0]]}
          ref="spotInspector"
          id={this.state.id}
          processInstanceId={this.state.processInstanceId}
          loginId={this.state.loginId}
          endTime={this.state.endTime}
          handleInfo={this.state.handleInfo}
          djFaultType={this.state.djFaultType}
         djReasonInfo={this.state.djReasonInfo}
         djHandleInfo={this.state.djHandleInfo}
         djHandleResult={this.state.djHandleResult}
         djOtherInfo={this.state.djOtherInfo}
         djMagorType={this.state.djMagorType}
/>

status 即 参数名
// 子组件使用props接收父组件传过来的参数

constructor(props) {
    super(props);
    this.state = {
      status: this.props.status,
      }}
      

在父页面第一次渲染时,即把status传给子组件了,
此时子组件拿到的是父组件里设置的this.state.status的默认值(比如 默认值为’’)
在父组件通过接口拿到数据后 再次渲染页面,会把新值传给子组件
此时子组件中的this.props.status值即随之改变。
但是在constructor中的state不会更新

在子页面中回显该值时 需要使用 this.props.status
父组件中该值改变时,给子组件传的参数 props.status也会随之改变,但是子组件中的state不会改变。
所以子页面中回显时需要使用this.props.status

这样会有一个别的问题,比如提交数据时 使用的 this.state.status,但是在父组件的值改变时,state不会随之更新(此时state的值是初始化的值)

只有在该input框更改时 触发onChange方法时会更新state,如果当前没有修改input框内容时,state不会更新,因此 可以通过将 下一次props中的值(这个为第二次渲染时拿到的新值)和state进行比较

// props改变时 更新state
componentWillUpdate(nextProps, nextState, nextContext) {
  // 先比较值是否一样
  if (this.state.pass !== nextProps.pass) {
    this.setState({
      pass: nextProps.pass
    })
  }
}

子组件给父组件传值
https://www.jianshu.com/p/ccc15c5963c4

10、下拉菜单 某个item颜色不同

onToggle={(t) => {
    console.log('t',t)
    if(dropdownStyle === "class2"){
        document.querySelectorAll('.class2 .epm-menu_item-title').forEach(el =>{ if (el.innerText.indexOf('item2') > -1 ){el.style.color = 'red'}})
    } else{
        document.querySelectorAll('.class1 .epm-menu_item-title').forEach(el =>{ if (el.innerText.indexOf('item2') > -1 || el.innerText.indexOf('item1') > -1){el.style.color = 'red'}})
    }
}}

11、function() 和 ()=>的区别

1)定义

//使用function定义的函数
function foo(){
	console.log(this);
}
// 箭头函数
var obj = { aa: foo };
foo(); //Window
obj.aa() //obj { aa: foo }

2)this指向
使用function定义的函数中this指向是随着调用环境的变化而变化的。
使用箭头函数的时候,this的指向是没有发生变化的。

3)构造函数
function是可以定义构造函数的,而箭头函数是不行的。

4)变量提升
由于js的内存机制,function的级别最高,而用箭头函数定义函数的时候,需要var(let const定义的时候更不必说)关键词,而var所定义的变量不能得到变量提升,故箭头函数一定要定义于调用之前!

foo(); //123
function foo(){
	console.log('123');
}

arrowFn(); //Uncaught TypeError: arrowFn is not a function
var arrowFn = () => {
	console.log('456');
};

12、React路由传参的三种方式

方式 一:
通过params
1.路由表中

  <Route path=' /sort/:id '   component={Sort}></Route>

2.Link处
1)HTML方式

<Link to={ ' /sort/ ' + ' 2 ' }  activeClassName='active'>XXXX</Link > 

2)JS方式

this.props.history.push(  '/sort/'+'2'  )

3.sort页面

   通过  this.props.match.params.id        就可以接受到传递过来的参数(id)

方式 二:
通过query
1、前提:必须由其他页面跳过来,参数才会被传递过来
注:不需要配置路由表。路由表中的内容照常:
2、Link处
1)HTML方式

2)JS方式

this.props.history.push({ path : ‘/sort’ ,query : { name: ’ sunny’} })

3、sort页面
this.props.location.query.name

方式 三:
通过state
1、同query差不多,只是属性不一样,而且state传的参数是加密的,query传的参数是公开的,在地址栏
2、Link 处
1)HTML方式:

 <Link to={{ path : ' /sort ' , state : { name : 'sunny' }}}> 
                  

2)JS方式:

this.props.history.push({ pathname:'/sort',state:{name : 'sunny' } })
                  

3、sort页面

this.props.location.state.name

13、React下载表格数据导出生成excel文件

1、安装依赖

npm install js-export-excel

2、引入依赖

import ExportJsonExcel from 'js-export-excel';

3、使用

downloadTest(){
    const option = {};
    // 文件名字
    option.fileName = '输煤系统报表';
    // 文件的数据集
    option.datas = [
        {
            // 通常用来放我们的表格数据
            sheetData: this.state.tableItems,
            // sheet名字
            sheetName: 'sheet',
            // 第一行
            sheetHeader: ['设备名称','纵向撕裂1','纵向撕裂2','跑偏跳闸','速度跳闸','跑偏报警','速度报警'],
            //列宽 需与列顺序对应, 需要则写
            // columnWidths: []


 }
    ]
    const toExcel = new ExportJsonExcel(option);
    let file = toExcel.saveExcel()
}

       

14、使用 moment 来获取日期

  1. 安装moment依赖
    npm install moment --save

  2. 引入moment依赖
    import moment from ‘moment’

  3. 使用

//获取 当前时间
moment().format('YYYY-MM-DD HH:mm:ss');   //2020-08-25 10:23:59

//获取年份
moment().year();       //2020
moment().get('year');  //2020

//获取月份(0:一月份  11: 12月份 )
moment().month();       //7
moment().get('month');  //7

//获取一个月的某一天
moment().date();       //25
moment().get('date');  //25

//获取小时
moment().hours();          //11
moment().get('hours');     //11

//获取分钟
moment().minutes();        //11
moment().get('minutes');   //11

//获取秒数
moment().seconds();        //17
moment().get('seconds');   //17

//获取 今天星期几
moment().format('dddd');     //Tuesday
moment().format('d');        //2

moment().day();              //2(0~6 分别代表周日到周六)
moment().weekday();          //2(0~6 分别代表周日到周六)
moment().isoWeekday();       //2(1~7 分别代表周一到周日)
moment().get('date');        //2
moment().get('weekday');     //2
moment().get('isoWeekday');  //2



设置时间

//设置年份
moment().year(2019);
moment().set('year', 2019);
moment().set({year: 2019});

//设置月份
//0~11, 0: 1月份, 11: 12月份
moment().month(8);        
moment().set('month', 8);



格式化时间
//格式化指定时间
moment(time).format('YYYY-MM-DD');


时间差
now_time.diff(start_time,"hour");      //小时数
now_time.diff(start_time,"minute");    //分钟数
now_time.diff(start_time,"second");    //现在和初始时间相差的秒数
now_time.diff(start_time, 'months');   //月数
now_time.diff(start_time, 'weeks');    //周数
now_time.diff(start_time, 'days');     //天数


相对时间
//add       加时间    
//subtract  减时间
moment().subtract(10, 'days').format('YYYY-MM-DD HH:mm:ss');  //2020-08-15 10:51:48
moment().subtract(6, 'days').format('YYYY-MM-DD HH:mm:ss');  //2020-08-19 10:51:48
moment().subtract(3, 'days').format('YYYY-MM-DD HH:mm:ss');  //2020-08-22 10:51:48
moment().subtract(1, 'days').format('YYYY-MM-DD HH:mm:ss');  //前一天:2020-08-24 10:51:48
moment().format('YYYY-MM-DD HH:mm:ss');                      //当前时间:2020-08-25 10:51:48
moment().add(1, 'days').format('YYYY-MM-DD HH:mm:ss');       //后一天:2020-08-26 10:51:48
moment().add(3, 'days').format('YYYY-MM-DD HH:mm:ss');       //2020-08-28 10:51:48
moment().add(10, 'days').format('YYYY-MM-DD HH:mm:ss');      //2020-09-04 10:51:48

moment().subtract(1, 'year').format('YYYY-MM-DD HH:mm:ss');  //前一年:
moment().add(1, 'year').format('YYYY-MM-DD HH:mm:ss');       //后一年:

moment().subtract(1, 'hours').format('YYYY-MM-DD HH:mm:ss');  //前一小时:
moment().add(1, 'hours').format('YYYY-MM-DD HH:mm:ss');       //后一小时:


// startOf 设置为起始时间 
moment("20111031", "YYYYMMDD").fromNow();    //9 years ago
moment().startOf('day').fromNow();           //11 hours ago
moment().startOf('hour').fromNow();          //an hour ago
moment().endOf('day').fromNow();             //in 13 hours
moment().endOf('hour').fromNow();            //in 15 minutes

//年初
moment().startOf('year').format('YYYY-MM-DD HH:mm:ss');   //2020-01-01 00:00:00
//月初
moment().startOf('month').format('YYYY-MM-DD HH:mm:ss');  //2020-08-01 00:00:00
//日初
moment().startOf('day').format('YYYY-MM-DD HH:mm:ss');    //2020-08-25 00:00:00
//周初  本周第一天(周日)
moment().startOf('week').format('YYYY-MM-DD HH:mm:ss');   //2020-08-23 00:00:00
//本周周一初
moment().startOf('isoWeek').format('YYYY-MM-DD HH:mm:ss');  //2020-08-24 00:00:00





 moment().startOf('day').format('YYYY-MM-DD HH:mm:ss') // 当天0点的时间格式
 moment().startOf('day').format('X') // 当天0点的时间缀,以10位Unix时间戳输出(秒)
 moment().endOf('day').format('YYYY-MM-DD HH:mm:ss') // 当天23点59分59秒的时间格式
 moment().endOf('day').format('x') //当天23点59分59秒以13位Unix时间戳输出(毫秒)

 moment('2020-06-30').startOf('day').format('x') // 2020-06-30当天0点的以13位Unix时间戳输出(毫秒)
 moment('2020-06-30').endOf('day').format('x') //  2020-06-30当天24点的以13位Unix时间戳输出(毫秒)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值