react17.x+MDUI实现todo小案例,react动态添加与删除元素属性

很长一段时间没有使用react做项目了,一看官网已经更新到17.x版本了,记得今年上班的时候才v13.x,由于平时项目开发用vue的时候居多,对于react长时间不用怕忘了,赶紧写个小案例练练手,使用版本说明:

  • react:v17.0.1
  • MDUI:v1.0.1
    官方描述:MDUI 漂亮、轻量且好用,它能让你更轻松地开发 Material Design 网页应用。官网地址https://www.mdui.org/

先上效果图:
react-todo效果图
至于为啥使用MDUI,我也是在头条上刷资讯的时候偶然看见的,因为平时在上面也会看一些前端相关的,时不时的就会一些推送过来,在这之前我也不知道有MDUI,看了官网后,我觉得还挺好看,样式布局等只需要添加对应的类名就可以了,特别喜欢上面的按钮涟漪动画效果,只需添加一个简单类名 .mdui-ripple 就可以实现,这里就不过多介绍了,详情可看官网。
在实现过程中一些问题:

  1. 使用create-react-app创建项目后编译过程很慢,每次更改文件保存时编译需要3~4秒的时间,问题是我新创建项目后就一个组件todo.js,根据网上找的一些方法亲测有效,方法如下:
    切换npm镜像,更换为淘宝的,然后删除node_modules包,重新cnpm install
npm config set registry http://registry.npm.taobao.org
  1. react动态添加与删除元素属性
    vue的动态绑定属性很方便,但react没有这种方式的写法,需要引入createRef
//vue的用法:
<a :[key]="url"> ... </a>
//react的用法
import React, { Component, createRef } from "react";
export default class Demo extends Component {
  state = { btn: createRef() };
  render() {
    return (
      <div ref={this.state.btn}> 操作添加属性</div>
    );
  }
  componentDidMount(){
      //通过this.state.btn.current操作
      //添加自定义属性,如data-id
      this.state.btn.current.setAttribute('data-id','10')
      //删除自定义属性
      this.state.btn.current.removeAttribute("data-id");
  }
}

注意,我这里使用的MDUI是用的cdn引入,需要在public文件下的index.html页面引入

<!-- MDUI CSS -->
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/mdui@1.0.1/dist/css/mdui.min.css"
  integrity="sha384-cLRrMq39HOZdvE0j6yBojO4+1PrHfB7a9l5qLcmRm/fiWXYY+CndJPmyu5FV/9Tw"
  crossorigin="anonymous"
/>

<!-- MDUI JavaScript -->
<script
  src="https://cdn.jsdelivr.net/npm/mdui@1.0.1/dist/js/mdui.min.js"
  integrity="sha384-gCMZcshYKOGRX9r6wbDrvF+TcCCswSHFucUzUPwka+Gr+uHgjlYvkABr95TCOz3A"
  crossorigin="anonymous"
></script>

Todo.js全代码

import React, { Component, Fragment, createRef } from "react";

export default class Todo extends Component {
  state = {
    num: 0, //未完成任务数量
    value: "", //输入的任务
    list: [
      //任务列表
      { id: "0", title: "阅读JavaScript权威指南第七版", check: false },
      { id: "1", title: "Css世界", check: false },
    ],
    btn: createRef(),
  };
  render() {
    return (
      <div className="mdui-card mdui-container-fluid">
        <div className="mdui-card-header">
          <h2
            className="mdui-card-header-title"
            style={{ textAlign: "center" }}
          >
            todolist案例
          </h2>
        </div>
        <div className="mdui-card-content">
          <div className=" mdui-row">
            <div className="mdui-textfield mdui-textfield-floating-label mdui-col-xs-6">
              <label className="mdui-textfield-label">请输入任务</label>
              <input
                className="mdui-textfield-input"
                type="text"
                value={this.state.value}
                onChange={this.getValue}
              />
            </div>
            <button
              className="mdui-btn mdui-btn-raised mdui-ripple mdui-color-purple"
              style={{ marginTop: "40px" }}
              onClick={this.handleAdd}
              ref={this.state.btn}
            >
              添加 +
            </button>
          </div>
          <ul className="mdui-list">
            {this.state.list.map((item, index) => {
              return (
                <Fragment key={item.title + index}>
                  <li className="mdui-list-item mdui-ripple">
                    <div className="mdui-list-item-content">
                      <label
                        className="mdui-checkbox mdui-text-color-purple"
                        style={{
                          textDecoration: item.check ? "line-through" : "none",
                        }}
                      >
                        <input
                          type="checkbox"
                          value={item.title}
                          onChange={this.handleCheck.bind(this, item)}
                        />
                        <i className="mdui-checkbox-icon"></i>
                        {item.title}
                      </label>
                    </div>
                    <i
                      className="mdui-list-item-icon mdui-icon material-icons"
                      onClick={this.handleDelete.bind(this, item, index)}
                    >
                      clear
                    </i>
                  </li>
                  <li className="mdui-divider"></li>
                </Fragment>
              );
            })}
          </ul>
          <div>
            <button className="mdui-btn mdui-btn-raised mdui-ripple mdui-color-purple-a700">
              未完成任务数量:<strong>{this.state.num}</strong></button>
          </div>
        </div>
        {/* 未输入任务名的弹出层 */}
        <div className="mdui-dialog" id="example-1">
          <div className="mdui-dialog-title">任务名不能为空!</div>
          <div className="mdui-dialog-content"></div>
          <div className="mdui-dialog-actions">
            <button className="mdui-btn mdui-ripple" mdui-dialog-confirm="true">
              确定
            </button>
          </div>
        </div>
      </div>
    );
  }
  //获取输入的任务名
  getValue = (e) => {
    this.setState({ value: e.target.value });
  };
  //添加任务
  handleAdd = () => {
    let { list, num, value } = this.state;
    if (!value) {
      this.state.btn.current.setAttribute(
        "mdui-dialog",
        "{target: '#example-1'}"
      );
      return;
    } else {
      this.state.btn.current.removeAttribute("mdui-dialog");
    }
    list.push({
      id: this.state.num + 1,
      title: this.state.value,
      check: false,
    });
    this.setState({ list, num: num + 1, value: "" });
  };
  //删除任务
  handleDelete(item, index) {
    let { list, num } = this.state;
    if (!item.check) {
      num--;
    }
    list.splice(index, 1);
    this.setState({ list, num });
  }
  //是否选择已完成
  handleCheck(item, e) {
    let { list, num } = this.state;
    list.forEach((p) => {
      if (p.title === item.title) {
        p.check = e.target.checked;
      }
      if (item.check === false) {
        this.setState({ num: num + 1 });
      } else {
        this.setState({ num: num - 1 });
      }
    });
    this.setState({ list });
  }
  componentDidMount() {
    let { num } = this.state;
    this.state.list.forEach((item) => {
      if (item.check === false) {
        num++;
        this.setState({ num });
      }
    });
  }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值