yingwinwin / yingwinwin.github.io

一个前端菜鸟的自我救赎之路...
https://yingwinwin.github.io/
8 stars 5 forks source link

React项目中遇到的小逻辑 #10

Open yingwinwin opened 4 years ago

yingwinwin commented 4 years ago

点击一下出现❌,再点击一次删除

import React, { Component } from 'react'

export default class App extends Component {
    constructor(){
        super();
        this.state = {
            arr : [],
            bigArr : [],
            current : ''
        }
    }

    componentWillMount(){
        let newArr = [];
        for(let i = 0 ; i < 20; i++){
            newArr.push(`第${i}项`)
        }

        this.setState({
            bigArr: newArr
        })
    }

    renderBtn(item,current){
        //这里判断,如果当前的current等于我点击的这个item的时候,渲染的item有一个x
        if(item === this.state.current){
            //第二次点击,把按钮删除。
            return <span onClick={()=>{
                this.setState({
                    arr: this.state.arr.filter(_item => item != _item)
                })
            }}>{item}x</span>
        }
        return <span>{item}</span>
    }

    render() {
        const { bigArr, arr } = this.state;
        //随意写的css
        const spanStyle = {
            'border':'1px solid #000',
            'padding': '5px',
            'margin':'3px',
        }
        return (
            <div>
                {/* 渲染上面的可点击删除标签 */}
                <div>
                    {
                        arr.map((item)=>{
                            // 点击外层div,为第一次点击,把item的值赋值给current。
                        return <div style={spanStyle} key = {item} onClick={()=>{
                            this.setState({
                               current: item
                            })
                        }}>{this.renderBtn(item)}</div>
                        })
                    }
                </div>
                <br/>
                {/* 渲染下面的标签添加到上面的数组中 */}
                <div>
                {
                    bigArr.map((item) => {
                        return <span style={spanStyle} key= {item} onClick={()=>{
                            //如果不存在点的时候添加数组,并清空current里面的值
                            if(!arr.includes(item)){
                                this.setState({
                                    arr:[...arr, item],
                                    current : ''
                                })
                            }else{
                                //如果存在,就删除
                                this.setState({
                                    arr:this.state.arr.filter(_item => _item != item)
                                })
                            }

                        }}>{item}</span>
                    })
                }
                </div>
            </div>
        )
    }
}

效果

image

yingwinwin commented 4 years ago

blur和click事件冲突web端解决

import React, { Component } from 'react'

export default class Back extends Component {
    render() {
        const divStyle = {
            'width':'200px',
            'height':'200px',
            'border':'1px solid #000'
        }
        return (
            <div>
                <input type="text" onBlur= {(e)=>{
                    console.log('blur')
                }}/>

                <div style={divStyle} onTouchEnd = {(e)=>{
                    console.log('click')
                }}>div</div>
            </div>
        )
    }
}

效果 image

yingwinwin commented 4 years ago

键盘事件

import React, { Component } from 'react'

export default class Keyboard extends Component {
    constructor(){
        super();
        this.state={
            value:'',
            arr:[]
        }
    }

    componentDidMount(){
        document.onkeyup = (e)=>{
            if(e.keyCode === 13){

                this.refs.input.blur()
                this.setState({
                    arr:[...this.state.arr,this.state.value],
                    value:''
                })
            }
        }
    }

    render() {
        return (
            <div>
                {
                    this.state.arr.map(item=>{
                        return <span key={item}>{item}</span>
                    })
                }
                <input type="text" ref="input" value={this.state.value} onChange={(e)=>this.setState({value:e.target.value})} />
            </div>
        )
    }
}

效果 image

yingwinwin commented 4 years ago

词语联想

import React, { Component } from "react";

export default class index extends Component {
  state = {
    value: "",
    assis: ["123", "高风险", "567", "234"],
  };

  handleChange = (e) => {
    this.setState({
      value: e.target.value,
    });
  };

  renderRed = (ele) => {
    if (ele) {
      const reg = new RegExp(`${this.state.value}`, "g");
      let times = 0; // 记录替换的次数
      const inputValueSplit = ele.split(reg);  // 分割当前的数组
      const replaceArr = [];
      ele.replace(reg, (...arg) => {
        replaceArr.push({ key: arg[0], keyValue: inputValueSplit[times] });
        times++;
      });
      return (
        <div>
          {replaceArr.map((item, index) => {
            return (
              <span key={ele + index}>
                {item.keyValue && (
                    /* 未匹配到的内容前面的内容 */
                  <span style={{ color: "red" }}>{item.keyValue}</span>
                )}
                {/* 匹配到的内容 */}
                <span style={{ color: "blue" }}>{item.key}</span>
              </span>
            );
          })}
          {/* 未匹配到的内容 */}
          {inputValueSplit[inputValueSplit.length - 1] && (
            <span style={{ color: "yellow" }}>
              {inputValueSplit[inputValueSplit.length - 1]}
            </span>
          )}
        </div>
      );
    }
  };

  renderList = () => {
    return this.state.assis.map((item) => (
      <li key={item}>{this.renderRed(item)}</li>
    ));
  };

  render() {
    return (
      <div>
        <input
          value={this.state.value}
          onChange={this.handleChange}
          type="text"
        />
        {
            this.state.value && <ul>{this.renderList()}</ul>
        }
      </div>
    );
  }
}

效果 image

yingwinwin commented 4 years ago

对象数组去重

  // 数组对象去重
  let person = [
     {id: 0, name: "小明"},
     {id: 1, name: "小张"},
     {id: 2, name: "小李"},
     {id: 3, name: "小孙"},
     {id: 1, name: "小周"},
     {id: 2, name: "小陈"},   
  ];

  let obj = {};

  // 方法1
  let peon = person.reduce((cur,next) => {
      obj[next.id] ? "" : obj[next.id] = true && cur.push(next);
      console.log(obj[next.id])
      return cur;
  },[]) 
  console.log(peon);

  let arr = [];
  // 方法 2
  for(let i = 0 ; i < person.length; i++) {
    if(!obj[person[i].id]) {
      arr.push(person[i]);
      obj[person[i].id] = true;
    }
  }
  console.log(arr) 
yingwinwin commented 4 years ago

react阻止浏览器默认事件报错

yingwinwin commented 4 years ago

picker组件

class App extends React.Component { state = { data: [ { id: "01", value: "北京市", child: [ { id: "00101", value: "北京市", child: [ { id: "000101", value: "东城区", }, { id: "000102", value: "西城区", }, { id: "000103", value: "朝阳区", }, ], }, ], }, { id: "02", value: "天津市", child: [ { id: "00201", value: "天津市", child: [ { id: "000201", value: "和平区", }, { id: "000202", value: "河东区", }, { id: "000203", value: "河西区", }, ], }, ], }, ], };

pca = (pca) => { console.log(pca); }; render() { return ; } }

export default App;


- 子组件
```jsx
import React, { Component } from "react";
import "./mulitPicker.css";

export default class MulitPicker extends Component {
  state = {
    prov: 0, // 省
    city: 0, // 市
    area: 0, // 区
    translateY: [0, 0, 0], // 移动Y
    startFinger: 0, // 手指刚开始点击的位置
    liHeight: 40, // li的高度
    pca: [], // 返回给父组件省市县的数组
  };

  /* 初始化省市区的值 */
  componentDidMount() {
    this.getPCA();
  }

  /**
   * @method hanleTouchStart
   * @param {object} e window事件对象
   * @return {null}
   */
  hanleTouchStart = (e) => {
    e.preventDefault();
    let startFinger = e.changedTouches[0].clientY; //获取初始手指触碰的值
    this.setState({
      startFinger,
    });
  };

  /**
   * @method hanleTouchMove
   * @param {object} e window事件对象
   * @param {number} idx 触碰的是第几列
   * @return {null}
   */
  hanleTouchMove = (e, idx) => {
    e.preventDefault();
    let nowFinger = e.changedTouches[0].clientY; // 获取移动是手指触碰的值
    let distance = nowFinger - this.state.startFinger; // 用移动时的位置-开始时候的位置 = 距离
    this.setState({
      translateY: this.state.translateY.map((item, index) => {
        // 如果是当前手指触碰的这列
        if (index === idx) {
          item += distance; // 就让translateY等于这个距离
        }
        return item;
      }),
    });
  };

  /**
   * @method hanleTouchEnd
   * @param {object} e window事件对象
   * @param {number} idx 触碰的是第几列
   * @param {number} len 触碰这一列的数组的长度
   * @return {null}
   */
  hanleTouchEnd = (e, idx, len) => {
    e.preventDefault();
    this.setState(
      {
        translateY: this.state.translateY.map((item, index) => {
          // 如果是当前手指触碰的这列
          if (index === idx) {
            item = item > 0 ? 0 : item; // 大于 0 ,说明用户是滑动的第一列,所以就只能是第一列,否则就是用户滑动的距离
            item =
              item < (-len + 1) * this.state.liHeight // 如果用户滑动的距离大于最大的数组长度 * 高的话,就让它等于当前的最大高,否则就是它滑动的距离
                ? (-len + 1) * this.state.liHeight
                : item;

            /* 求出用户多滑的位置 */
            let sub = item % this.state.liHeight;
            //如果多滑的位置,小于一半,就让它回到原来的,否则就加一个
            if (sub < this.state.liHeight / 2) {
              item = item - sub;
            } else {
              item = item + (this.state.liHeight - sub);
            }
          }
          return item;
        }),
      },
      () => {
        this.setPCA(idx); //在回调里调用得到当次的值
      }
    );
  };

  /* 确定按钮 */
  handleSure = () => {
    this.props.pca(this.state.pca); // 给父组件返回值
  };

  /* 设置省动其他也动 */
  setProv = () => {
    let temp = [...this.state.translateY];
    temp[1] = 0;
    temp[2] = 0;
    this.setState(
      {
        prov: Math.abs(this.state.translateY[0]) / 40,
        city: 0,
        area: 0,
        translateY: temp,
      },
      () => {
        this.getPCA();
      }
    );
  };

  /* 设置城市动其他也动 */
  setCity = () => {
    let temp = [...this.state.translateY];
    temp[2] = 0;
    this.setState(
      {
        prov: Math.abs(this.state.translateY[0]) / 40,
        city: Math.abs(this.state.translateY[1]) / 40,
        area: 0,
        translateY: temp,
      },
      () => {
        this.getPCA();
      }
    );
  };

  /* 设置区的内容 */
  setArea = () => {
    this.setState(
      {
        area: Math.abs(this.state.translateY[2]) / 40,
      },
      () => {
        this.getPCA();
      }
    );
  };

  /* 设置省市区三省联动  idx为滑动的每一列*/
  setPCA = (idx) => {
    const setMethod = new Map([
      [0, this.setProv],
      [1, this.setCity],
      [2, this.setArea],
    ]);
    setMethod.get(idx)();
  };

  /* 得到省市县的值传给父组件 */
  getPCA = () => {
    const { data } = this.props;
    const { prov, city, area } = this.state;
    let p = data[prov].value;
    let c = data[prov].child[city].value;
    let a = data[prov].child[city].child[area].value;
    this.setState({
      pca: [p, c, a],
    });
  };

  /**
   * @method hanleTouchEnd
   * @param {object} data 父组件传过来的转换后的值
   * @param {number} p 传过来省的数组的位置
   * @param {number} c 传过来市的数组的位置
   * @return {null}
   */
  renderPickerCol = (data, p, c) => {
    if (!data) return;
    let prov = data;
    let city = data[p].child;
    let area = data[p].child[c].child;
    return [prov, city, area].map((item, idx) => (
      <ul
        key={idx}
        className="picker-ulCol"
        style={{
          transform: `translate3d(0, ${this.state.translateY[idx]}px, 0)`,
          transition: `transform 0.2s ease-out`,
        }}
        onTouchStart={(e) => this.hanleTouchStart(e)}
        onTouchMove={(e) => this.hanleTouchMove(e, idx)}
        onTouchEnd={(e) => this.hanleTouchEnd(e, idx, item.length)}
      >
        <li className="picker-list"></li>
        <li className="picker-list"></li>
        {this.renderPickerList(item)}
        <li className="picker-list"></li>
        <li className="picker-list"></li>
      </ul>
    ));
  };

  renderPickerList = (item) => {
    return item.map((ele) => (
      <li key={ele.id} className="picker-list">
        {ele.value}
      </li>
    ));
  };

  render() {
    return (
      <div className="picker-wrap">
        <div className="picker-title">
          <div className="picker-cancel">取消</div>
          <div className="picker-sure" onClick={this.handleSure}>
            确定
          </div>
        </div>
        <div className="picker-content">
          {this.renderPickerCol(
            this.props.data,
            this.state.prov,
            this.state.city
          )}
          <div className="picker-mid"></div>
        </div>
      </div>
    );
  }
}

ul li { list-style: none; }

.picker-wrap { width: 100%; height: 250px;

.picker-title { position: relative; width: 100%; height: 50px; display: flex; justify-content: space-between; padding: 0 20px; box-sizing: border-box; line-height: 50px; z-index: 3; }

.picker-content { display: flex; position: relative; .picker-ulCol { flex: 1; height: 200px; z-index: 2;

  .picker-list {
    height: 40px;
    line-height: 40px;
    text-align: center;
    z-index: 2;
  }
}

.picker-mid {
  position: absolute;
  top: 80px;
  width: 100%;
  height: 40px;
  border-bottom: 1px solid #ccc;
  border-top: 1px solid #ccc;
  z-index: 1;
}

} }



![image](https://user-images.githubusercontent.com/55273635/82153016-8958c000-9897-11ea-84a6-4cabb0805bb8.png)