zoukankan      html  css  js  c++  java
  • react项目经验

    调用后返回上一页&&跳转至当前页

     this.props.history.goBack();   返回
     this.props.history.push("/index/setting/basicsetting"); 跳转
     this.props.history.go(-1)  跳转
    
    当使用时出现以下错误Cannot read property 'push' of undefined,
    因为父组件调用子组件定义的跳转事件时,要传递history,这里history未定义
    (比如app.js这个组件,一般是首页,不是通过路由跳转过来的,而是直接从浏览器中输入地址打开的,如果不使用withRouter此组件的this.props为空,没法执行props中的history、location、match等方法)
    解决方法:
    import React from "react";
    import {withRouter} from "react-router-dom";   //第一,引入withRouter
    
    class MyComponent extends React.Component {   
      ...
      myFunction() {
        this.props.history.push("/some/Path");
      }
      ...
    }
    export default withRouter(MyComponent);   //第二,不要在上面暴露模块,在这里使用withRouter暴露模块
    
    详细可见:react-router v4 使用 history 控制路由跳转   https://github.com/brickspert/blog/issues/3
    

    调用后重新渲染当前页&&跳转至当前页

     this.props.history.go(0)  跳转
    
    
    
     state={
       visible:false
     }
     handleClick=()=>{
        this.setState({
           visible:true
         });
       }
     this.setState(this.state)  //此语句执行过后页面重新渲染state。这里需要注意的事重新渲染会将visible渲染成state里的false,而不是handleClick里的true
    //渲染会把state里的内容全部重新渲染,即执行this.setState(state)之后,visible会被重新渲染为false,若需要visible为true,可以在渲染之后重新定义状态,如下重新定义
     this.setState({this.state})
     this.setState({
          visible:true
       });
    
    
    
     定义componentWillMount=async()=>{   
            this.getData(); //重新渲染当前页面
        }  // 使用:调用this.getData();函数即可
        async getData(){
            代码段
        }
    
    

    代码解析

    let {state}=this;  // 即 let state = this.state;
    
    let res = await api.SettingGetInfo(this.props.match.params)   //获取列表里当前元素的id值,此方法需要注意有一个必要条件在route页面里的route添加  /:id
    //即<Route path="/index/setting/basicsetting/:id" component={BasicSettting} />
    
    
    rowKey={record=>record.id}    //表格table中的每个记录应该有唯一的“key”支持,或者将“rowKey”设置为唯一的主键,否则会报错。这里是给表格设置rowKey
    

    点击按钮复制相关内容(这里以复制链接为例)

      npm i --save copy-to-clipboard   //首先安装相关包
    
      import copy from 'copy-to-clipboard';  //引入模块
    
      render:(a, code, index)=>{
                    return <span>
                        <a href="# "  onClick={()=>{this.copyLink(code)}}>复制链接</a>
                    </span>
                }
    
      copyLink=(code)=>{
            copy(`https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=${code.info}`)
            message.success("链接复制成功",2.5)
        }
    
    

    三目运算符的嵌套使用

    正常使用:code.type===1?(adate<bdate?atime:btime):<span className="text-success">永不</span>
    
    react里:{title:"时间",dataIndex:"Time",render(a,code,index){
                    let adate=...;
                    let bdate=...;
                    var overtime=<span className="text-danger">时间不足</span>;
                    var forevertime=<span className="text-success">永久</span>
                    var times=`${date.getFullYear()}-${date.getMonth() + 1<10?"0"+(date.getMonth()+1):date.getMonth()+1}-${date.getDate()<10?"0"+date.getDate():date.getDate()} ${date.getHours()<10?"0"+date.getHours():date.getHours()}:${date.getMinutes()<10?"0"+date.getMinutes():date.getMinutes()}:${date.getSeconds()<10?"0"+date.getSeconds():date.getSeconds()}`   //将时间戳转换为日期格式
    
                    return <span>{code.type===1?(adate<bdate?overtime:times):forevertime}</span>  //嵌套使用
                }}
    

    ======================================================================================================================================================

    接口部分

    读懂接口文档

    
    /api/wechat/code/:officialId/:qrcodeId  带冒号,动态数据:`${base}/api/wechat/code/${localStorage.getItem("listid")}/${params.id}`  //这列的:qrcodeId需要使用${params.id}动态写入,params即数组
    /api/wechat/statistics/:officialId/code  不带冒号,静态的:`${base}/api/wechat/statistics/${localStorage.getItem("listid")}/code`  //这里的qrcode直接写上去就可以
     
    

    参数问题

      request<T = any>(config: AxiosRequestConfig): AxiosPromise<T>;   //request 一个参数  config
      get<T = any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>;  //get  两个参数 url config
      delete(url: string, config?: AxiosRequestConfig): AxiosPromise;  //delete  两个参数  url config
      head(url: string, config?: AxiosRequestConfig): AxiosPromise;   //head  两个参数 url config
      post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>;  //post 三个参数 url data config
      put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>; // put 三个参数 url data config
      patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>; // patch 三个参数 url data config
    
    参数解释 :url —— 请求地址
                       data——发送给服务器的请求数据
                       config——配置,一般都是固定格式
    
    举个栗子:
      export default{
            async codeDesign(params){                                                 
                    return await axios.put(`${base}/api/code/${localStorage.getItem("listid")}/${params.id}`, params,{  //url data
                              headers:{                         //config  一般都是固定格式
                                   "token":cookie.load("usertoken")
                              }
                    }).then((res)=>{
                          return res.data;
                    });
           },
            async codeExtend(params){
            return axios.post(`${base}/api/code/${localStorage.getItem('listid')}/${params.id}/extend`,{},{   //这里data就没有传参,而是用{}表示
                headers:{
                    "token":cookie.load("usertoken")
                }
            }).then((res)=>{
                return res.data;
            });
        },
          async codeGetMsg(params){
                  return await axios.get(`${base}/api/code/${localStorage.getItem("listid")}/${params.id}`,{
                      params,       **//如果是get delete两个参数的这种,是没有data参数的,那么params不能放在data里,就可以放在config里**
                      headers:{
                          "token":cookie.load("usertoken")
                      }
                  }).then((res)=>{
                      return res.data;
                  });
              },
      }
    
    注意:需要的参数,一个都不能少,data如果不需要传,设置为{}都行,也不能不传
    
    

    axios实战举例

    state={
    
        //上传接口的参数
        title:"",   
        author:"",
        digest:"",
        content:"",
    
        piclist:[],   //从服务器获取的图片数组
        picTotal:2,   
        filter:{         
            isloading:false,
            type:"image",
            flag:2,
            page:1,
            pageSize:18,
          },
    }
    
    //上传pictextData数据到服务器
        addPictext=async()=>{
            let {title,author,digest,content}=this.state.pictextData;
            if(!title){
                this.setState({
                    pictextTitleRemind:true
                })
                return;
            }else{
                this.setState({
                    pictextTitleRemind:false
                })
            }
            if(!(/^(((https?)://|w+(.w+)+)(:w+)?).*/.test(contentSourceUrl))){   //匹配正则
                this.setState({
                    urlRemind:true
                })
                return;
            }else{
                this.setState({
                    urlRemind:false
                })
            }
            let data=await api.pictextAdd({
                title,
                author,
                digest,
                content,
            })
            if(data.code!==0){
                console.log(api.stateCode[data.code]);
                return;
            }
            if(data.code===0){
                message.success("保存成功!",3);
                this.props.history.push("/index/setting/pictextIndex");
            }
        }
    
    componentWillMount=async()=>{   //render加载之前就获取到图片信息
          this.getData();
        }
    
    //获取图片的接口
    async getData(){
          this.setState({
            filter: Object.assign(this.state.filter, {
                isloading: true
            }),
            
          });
          let res=await api.picGetList(this.state.filter)
         this.setState({
            filter: Object.assign(this.state.filter, {
                isloading: false
            }),
          if(res.code===0){
            this.state.picTotal=res.data.total;
            this.state.piclist=res.data.data;
          }else{
            console.log(api.stateCode[res.code]);
          }
          this.setState(this.state);  //重新渲染页面
        }
    
    //分页
        onChangePage = (page = 1, pageSize = 18) => {
          this.setState(
              Object.assign(this.state.filter, {
                  page,pageSize
              })
          );
          this.getData();  //重新加载getData函数,为了重新渲染页面
        }
    
    //删除图片接口
        deletePic=async(item)=>{
          this.setState({
            imgDelete:false,
            picImgDelete:false,
          })
          let data=await api.picDelete({
            id:item.id,    //获取需要删除的图片的id
          })
          if(data.code!==0){
            console.log(api.stateCode[data.code]);
            return;
          }else if(data.code===0){
            this.onChangePage();
            message.success(`删除成功!`,2.5);
          }
          this.getData();
        }
    
    <Pagination hideOnSinglePage onChange={this.onChangePage} current={this.state.filter.page} pageSize={this.state.filter.pageSize} total={this.state.picTotal}  />  //antd分页页标
    

    受控组件和不受控组件

    在HTML中,<textarea> 的值是通过子属性设置的。在React中,需要通过value设置。我们可以通过添加事件属性onChange监听内容的变化,onChange会在下列情况下被触发:
    input或者textarea的内容改变
    input的checked状态改变
    select的状态改变
    
    【受控组件】
    设定了value的input就是一个受控组件。input里会一直展现这个值,用户的任何输入都是无效的。如果你想随着用户的输入改变,使用onChange事件,或者将value改为defaultValue
    
    【非受控组件】
    value没有值或者值设为null的input是一个不受控组件。用户的任何输入都会反映到输入框中
    这个时候也可以监听onChange事件,内容的改变也会触发事件。
    可以通过defaultValue给input设置默认值
    

    指定编辑(如删除,更新等)

    有一种需求是点击table中当前tr的“编辑”按钮后,跳转到新的编辑页面编辑当前tr的信息。
    这种情况是需要动态获取id的
    方法如下:
    1、在route.js即路由页面将编辑页面的路由给一个/:id,如下
    <Route path="/index/setting/code/code-edit/:id" component={codeEdit} />   //注意是/:id  /别忘了
    2、列表页面编辑按钮的Link跳转给一个动态id(该id由后端接口数据里给出),如下
    <Link to={`/index/setting/code/code-edit/${codelist.id}?id=${codelist.id}`} className="mr-10px">编辑</Link>
    3、在编辑页面对接接口时,参数应使用this.props.match.params
    async getPictextData(){
            let res =await api.pictextGetEdit(this.props.match.params)   //这里传入的是this.props.match.params
            if(res.code===0){
                state.pictextEditData=res.data;
            }else{
                console.log(api.stateCode[res.code]);
            }
            this.setState(state)
          }
    
    提个醒:this.props.match.params是从另一个页面通过路由带到当前页面的数据。你可以在任何地方使用它。
    这也表明了,这个传递的数据,不一定得是id,也可以是其他的数据。比如name,size等,通过/:name就可以传递
    就比如说console.log(this.props.match.params)打印出来的是{"id":"1"}。你就可以通过this.props.match.params.id来获取到1。
    但有一点,这个1可能是字符串类型的。和number类型的不是一个数据类型。所以在做判断是否相等的时候要注意,用==而不用===
    在控制台打印出的数字,黑色的就是string类型。蓝色的是number类型
    
    

    使用搜索框搜索数据(后端接口没有设置好,全部由前端操作)

    state={
        filter: {
                    name:"",
                    total: 0,
                    page:1,
                    pageSize:20,
                }
    }
    
    handleProductSearch=(e)=>{
            this.setState(
                Object.assign(this.state.filter,{
                    name:e.target.value,   //在对接接口之后。若想根据名称name搜索,将搜索框的event赋值给filter里的name便可
                })
            );
            this.setState(state);  //重新渲染页面
        }
    
    
    <Search
        placeholder="请输入产品名称"
        onSearch={this.handleProductSearch}
    />
    

    使用搜索框搜索数据,(后端接口已经设置好的情况下)

    state={
        filter: {
                    name:"",
                    total: 0,
                    page:1,
                    pageSize:20,
                }
    }
    
    productName=(e)=>{
         this.setState(
                Object.assign(this.state.filter,{
                    name:e.target.value,   //在对接接口之后。若想根据名称name搜索,将搜索框的值赋值给filter里的name便可
                })
            );
    }
    
    handleProductSearch=(e)=>{
            this.productInfoGet();  //调用获取产品信息的接口。此时的name已经是搜索的name。给接口接口会返回搜索后的结果
        }
    
    
    <Search
        placeholder="请输入产品名称"
        onChange={this.productName}
        onSearch={this.handleProductSearch}
    />
    

    ======================================================================================================================================================

    localStorage解释

        localStorage.setItem("key","value");//以“key”为名称存储一个值“value”
    
        localStorage.getItem("key");//获取名称为“key”的值
    
        localStorage.removeItem("key");//删除名称为“key”的信息。
    
        localStorage.clear();​//清空localStorage中所有信息
    

    state里的filter里得数据怎么setState?(使用Object.assign相关知识)

    this.state={
                visible:false,
                filter: {
                    isloading: false,
                    name:"",
                    page:1,
                    pageSize:20,
                }
            }
    
    这里的isloading怎么设置为true呢?
    
    handleClick=()=>{
            this.setState({
                filter:Object.assign(this.state.filter,{
                    isloading:true
                }),
            });
        }
    

    动态添加css样式(如通过点击添加css样式)

    state={
        select: "",
    }
    
    handleSelect=(item)=>{
        this.setState({
            select: item.id
        })
    }
    
    <div onClick={()=>{this.handleSelect(item)}}  style={{border:this.state.select===item.id?"1px solid #28a745":null}}></div> 
    

    动态添加一组可编辑框(如点击添加按钮后会添加一个可输入数值的图文框)

    思路:
    1、state一个数组如Data,将数组的值与图文框绑定起来,通过map函数渲染到页面
    2、当点击添加按钮后,执行函数,往list数组里push一组数据,数据会自动渲染到页面,即实现了动态添加图文框的功能
    3、通过编辑数组的值即可动态编辑图文框里的内容
    4、动态删除可以通过用数组的splice操作数组的下标index来实现删除。
    总结:通过操作数组的数据来实现图文框的增删改,而不是通过dom操作
    
    举个例子:
    state={
        title:"",     //上传接口的参数
        author:"",
        digest:"",
        content:"",
        Data:[{id:"1",title:"",author:"",digest:"",content:""}],
        boxid:"1", //定义图文框的id
        msg:[],
        changeBorder:"",
    }
    
    //添加图文框数组
        addBox=()=>{
            this.setState({
                boxid:this.state.boxid++, 
            })
            this.state.Data.push({id:`${this.state.boxid}`,title:"",author:"",digest:"",content:""})
            this.setState(this.state)
        }
    //删除图文框
    listbox_Delete=(item)=>{  
            let index= this.state.Data.indexOf(item)    //获取需要删除的图文框的index
            this.state.Data.splice(index,1)    //使用splice方法删除数组数据
        }
    
    //向上移动图文框(通过改变替换index来实现)
    listbox_up=(item)=>{
            let index=this.state.Data.indexOf(item)
            let arr=this.state.Data
            let index2=index-1
            if(index2!==0){
                arr[index]=arr.splice(index2,1,arr[index])[0] 
            } 
        }
    
    //向下移动图文框
    listbox_down=(item)=>{
            let index=this.state.Data.indexOf(item)
            let arr=this.state.Data
            let index2=index+1
            if(index2!==arr.length){
                arr[index]=arr.splice(index2,1,arr[index])[0]
            }
        }
    
    //图文框数组map方式渲染到页面
    {
             this.state.Data.map((item,index)=>{
             if(item.id==1){   //item.id==1时是主图文框的样式,否则是副图文框的样式
             return <div onClick={()=>{this.handleSelect(item)}} key={index}>   //map语法必须要带有key={index},不然会报错
                             <div  >
                                 <img src={item.picUrl} alt="" style={{"100%",height:"100%"}}/>
                             </div>
                             {item.title?<div className="indexbox_mask">{item.title}</div>:null}
                         </div>
                      }else{
                   return <div  key={index} style={{border:this.state.changeBorder===item.id?"2px solid #28a745":null}} onClick={()=>{this.handleSelect(item)}}>    //handleSelect,点击后选取当前框并与输入框绑定
                                  <h4 style={{height:21}}>{item.title}</h4>
                                  <div className="listbox_content">
                                        <div className="listbox_img">
                                                <img src={item.picUrl} alt=""/>
                                        </div>
                                  </div>
                                  <div className="listbox_mask">
                                          <Icon type="up"className="listbox_icon mr-10px" onClick={()=>{this.listbox_up(item)}} />  //图文框位置上移
                                          <Icon type="down" className="listbox_icon" onClick={()=>{this.listbox_down(item)}} />  //图文框位置下移
                                          <div className="float-r">
                                               <Icon type="delete"className="listbox_icon" onClick={()=>{this.listbox_Delete(item)}}/>   //删除图文框
                                          </div>
                                   </div>
                              </div>
                           }
                     })
                 }
        <Button onClick={this.addBox}></Button>  //添加图文框
    
    //点击图文框后选定当前图文框,并与Input输入框绑定,之后在Input里输入的值都会存在当前数组里。再点击其他图文框后执行同样的操作,最后所有图文框里采集的数据会全部存在Data数组里,通过接口将数组传入后台,再在另一个页面获取并渲染该组数据,即完成了前后端的一个交接流程。
    handleSelect=(item)=>{
            console.log(item)
            this.setState({
                msg:item,
                changeBorder:item.id,
                title:item.title,
                author:item.author,
                digest:item.digest,
                content:item.content,
            })
        }
    
    handleGetTitle=(e)=>{     //与Input标签之间进行双向绑定
            this.setState({
                title:e.target.value,
            })
            this.state.msg.title=e.target.value;    //使得输入框与当前选定的文本框绑定
        }
    
    <Input  onChange={this.handleGetTitle} id={this.state.msg.id} value={this.state.title} placeholder="请输入标题"/>
    

    antd图片上传

    //判断用户上传文件的格式,不符合提醒用户,符合则返回true
    function beforeUpload(file) {
      if(file.type!=='image/png'&&file.type!=='image/jpeg'&&file.type!=='image/jpg'&&file.type!=='image/gif'){
        message.error("上传失败!仅支持jpeg,png,jpg,gif图片格式");
        return false;
      }else if(file.size/1024/1024>4){
        message.error("上传失败!仅支持大小在4M以内的图片上传");
        return false;
      }
      return true;
    }
    
    //上传图片接口
        UploadImg=()=>{
          let self= this;    
          return {
            name: 'media',
            action: `  `,  //这里写服务器地址
            headers: {    //设置请求头
              token: cookie.load('usertoken'),
            },
            onChange(info) {
              self.setState({
                uploadWaiting:true
              })
              if (info.file.status !== 'uploading') {
                console.log(info.file, info.fileList);
                self.setState({
                  uploadWaiting:false,
                })
              }
              if (info.file.status === 'done') {
                message.success(`${info.file.name}上传成功!`);
                self.setState({
                  uploadWaiting:false,
                })
                self.getData()
              } else if (info.file.status === 'error') {
                message.error(`${info.file.name}上传失败!`);
                self.setState({
                  uploadWaiting:false,
                })
              }
            },
          }
        }
    
        <Upload {...this.UploadImg()} beforeUpload={beforeUpload}><Button>上传图片</Button></Upload>
    

    列表数据相关操作(table)

    constructor(props){
            super(props);
            this.columns=[
                {title:"",
                dataIndex:"ticket",
                66,
                render:(record)=>(<img src={record} width="50px" alt="" />)    
                },
                {title:"产品名称",dataIndex:"name"},
                {title:"产品类型",dataIndex:"type", render(a, productlist, index){
                    return <span>{productist.type || "无"}</span>
                }},
                {title:"对应编码",dataIndex:"keyword"},
                {title:"生产时间",dataIndex:"createtime"},
                {title:"到期时间",dataIndex:"expiretime",render(a,productlist,index){
                    let date=new Date(new Date(productlist.expireTime).getTime());
                    let nowdate=new Date(new Date().getTime());
                    var overtime=<span className="text-danger">已过期</span>;
                    var forevertime=<span className="text-success">永不</span>
                    var times=`${date.getFullYear()}-${date.getMonth() + 1<10?"0"+(date.getMonth()+1):date.getMonth()+1}-${date.getDate()<10?"0"+date.getDate():date.getDate()} ${date.getHours()<10?"0"+date.getHours():date.getHours()}:${date.getMinutes()<10?"0"+date.getMinutes():date.getMinutes()}:${date.getSeconds()<10?"0"+date.getSeconds():date.getSeconds()}`
                    return <span>{productlist.mode===1?(date<nowdate?overtime:times):forevertime}</span>
                }},
                {title:"操作",
                dataIndex:"operation",
                key:"operation",
                225,
                render:(a, qrcodelist, index)=>{
                    return <span>
                        <a href="# " className="mr-10px" onClick={()=>{this.copyLink(qrcodelist)}}>复制链接</a>
                        <a href={`${productlist.ticket}`} target={"_blank"} download={`${productlist.name}`} className="mr-10px">下载产品</a>
                        <Link to={`/index/setting/product/product-edit/${productlist.id}?id=${productlist.id}`} className="mr-10px">编辑</Link>
                        {productlist.mode===2 ? <a href="# "  onClick={()=>{this.showModal2(productlist)}}>删除</a> : <a href="# " onClick={() => {this.extendProduct(productlist)}}>延时上架</a>}
                    </span>
                }
                
            },
            ];
            this.state={
                visible:false,
                visible2:false,
                productlist:[],
                filter: {
                    isloading: false,
                    name:"",
                    total: 0,
                    page:1,
                    pageSize:20,
                }
            }
            
        }
    
    
    <Table 
      columns={this.columns} 
      dataSource={this.state.productlist} 
      rowKey={record=>record.id}    //表中的每个记录应该有唯一的“key”支持,或者将“rowKey”设置为唯一的主键,否则会报错。这里是给表格设置rowKey
      pagination={{onChange:this.onChangePage, current: this.state.filter.page, pageSize: this.state.filter.pageSize , total: this.state.filter.total }} /> 
    
    注意:这里涉及到两种render写法,两种写法的this指向不同,其他效果差不多
    1、render:(a,b)=>{
                let time=a,
                let overtime=b,
                return <div>......</div>
           }
    2、render(a,b){
            let time=a,
            let overtime=b,
            return <div>......</div>
        }
                            
    

    滚动监听及回到顶部

    state={
        backTop:false,
        backTopShow:false,
    }
    
    componentWillMount=()=>{
            window.addEventListener("scroll",this.handleScroll,true)    //滚动监听
        }
    
    handleScroll=()=>{
            if(document.documentElement.scrollTop>1000){
                this.setState({
                    backTopShow:true,    //当滚动到距离顶部1000px的距离时,“回到顶部”按钮显示
                })
            }else{
                this.setState({
                    backTopShow:false,
                })
            }
            if(document.documentElement.scrollTop===0){   //当滚动到 0时,清除定时器
                clearInterval(this.scrollTimes)
            }
        }
    
    backToTop=()=>{
            if(document.documentElement.scrollTop>0){
                this.scrollTimes=setInterval(()=>{
                    document.documentElement.scrollTop=document.documentElement.scrollTop-60;
                },5)
            }
        }
    
    
    {this.state.backTopShow?<Button onClick={this.backToTop}>回到顶部</Button>:null}    //“回到顶部”按钮
    

    关于接口调用函数的写法

    间接调用,被动触发式用这种写法,这种写法用onClick等主动触发可能会引起Cannot read property 'setState' of undefined错误
    async userInfoGet(){
            let res=await api.getUserInfo()
            if(res.code===0){
                this.setState({
                    userNickname:res.data.nickname
                })
            }else{
                console.log(api.stateCode[res.code]);
            }
        }
    componentWillMount(){
        this.userInfoGet()
    }  //在别的函数里间接触发
    直接调用,主动触发式如onClick等,用这种写法
    userInfoGet=async()=>{
            let res=await api.getUserInfo()
            if(res.code===0){
                this.setState({
                    userNickname:res.data.nickname
                })
            }else{
                console.log(api.stateCode[res.code]);
            }
        }
    <Button onClick={this.userInfoGet}></Button>  //主动调用
    

    将React.Component外部的代码移入到其内部

    外部:
    const props = {
      name: 'file',
      action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
      headers: {
        authorization: 'authorization-text',
      },
      onChange(info) {
        if (info.file.status !== 'uploading') {
          console.log(info.file, info.fileList);
        }
        if (info.file.status === 'done') {
          message.success(`${info.file.name} file uploaded successfully`);
        } else if (info.file.status === 'error') {
          message.error(`${info.file.name} file upload failed.`);
        }
      },
    };
    
    export default class Demo extends React.Component{}
    
    内部:
    export default class Demo extends React.Component{
        state={}
        pluginZipUpload=()=>{
            let self=this;    //这里改动 let self=this
            return{   //这里改动return
                name: 'plugin',
                action: "https://www.mocky.io/v2/5cc8019d300000980a055e76",
                headers:{
                    authorization: 'authorization-text',
                },
                onChange(info) {
                  if (info.file.status !== 'uploading') {
                    console.log(info.file, info.fileList);
                  }
                  if (info.file.status === 'done') {
                    self.setState({
                        pluginAddFile:Object.assign(self.state.pluginAddFile,{     //这里this换成self
                            plugin: info.file.originFileObj
                        })
                    })
                    console.log(self.state.pluginAddFile.plugin)
                  } else if (info.file.status === 'error') {
                    message.error(`${info.file.name}上传失败`);
                  }
                },
            }
          };
    
    }
    

    如何知道函数里需要传几个参数或者判断函数里有几个参数

    es5里可以用arguments打印
    es6里可以用拓展运算符...a方法
    在函数里写入...params
    handleUpload=(...a)=>{}
    console.log(...a)即可打印出来里面需要的参数
    
    可搭配debugger使用
    
  • 相关阅读:
    说明因 Active Directory 冲突导致的 NTDS 复制警告 ID 1083 和 1061 以及 SAM 错误 ID 12294
    KB817701:可用于解决帐户锁定问题的 Service Pack 和修复程序
    log check
    AD account 锁定问题
    VS.2005 中比较有用的快捷键
    用户帐户意外锁定, 以及 Windows Server 2003 中记录事件 ID 12294
    xp 重新安装MDAC
    [学习收藏]业界三种架构优缺点比较
    [收藏学习]Linux内核虚拟机 学习KVM架构及其优点
    两个命令:hdparm和iozone参数解释
  • 原文地址:https://www.cnblogs.com/huihuihero/p/10921507.html
Copyright © 2011-2022 走看看