react新手demo——TodoList

react

 

react-todolist.gif

一: 写在文章开头

今天我们就使用 react 来实现一个简易版的 todolist ,我们可以使用这个 demo 进行 list 的增删改差,实际效果如上图所示。大家可以clone下来查看:react-todolist

这篇文章我们就不使用 redux,因为这个 demo 本身比较简单,不需要通过 redux 来管理我们的状态。

redux中也有非常有名的一句话叫做:

"如果你不知道是否需要 Redux,那就是不需要它。"

我们废话不多说,直接进入正题。


二:项目的目录结构

   .

├── app // 开发的文件夹,组件放在这个文件夹中

│ ├── components // 项目的组件

│ │ ├── App.js // 最外层包含下面组件的总组件

│ │ ├── AppFooter.js // App的三个筛选按钮的组件

│ │ ├── AppForm.js // 添加list的form

│ │ ├── AppList.js // 显示list数据的智能组件

│ │ └── AppTodos.js // 显示list的木偶组件

├── css // 放css文件的地方。

│ ├── semantic.css // 我们的文件用到了semantic.css,

├── node_modules // 第三方的依赖

├── .babelrc // babel配置文件

├── .gitignore // git上传时忽略的文件

├── bundle.js // webpack build之后的文件

├── index.html // 项目的模版文件

├── main.js // 项目的入口文件

├── webpack.config.js // webpack配置文件

├── README.md // readme文件

└── package.json // 当前整一个项目的依赖


三:前期准备,安装依赖

1,首先我们新建一个todolist文件夹,根据我的目录结构建好相应的文件,如果大家嫌麻烦,大家可以clone我的项目,然后看着我的代码,我会一一进行说明的。package.json我们可以自己创建。

$ mkdir todolist

$ cd todolist

2,建立package.json文件

npm init

3,安装相应的依赖,我先解释一下这些依赖的作用

  • 首先安装Babel,Babel 是一个 JavaScript 编译器,他可以将es6或者es7的语法转化为浏览器能识别的javascript。

    npm install babel-cli babel-core --save-dev

  • 其次安装我们的主角,react

    npm install react react-dom --save-dev

  • 安装webpack,打包工具;和webpack-dev-server,用于来给我们开启一个服务的。

    npm install webpack webpack-dev-server --save-dev

  • 安装loader打包,通过使用不同的loaderwebpack有能力调用外部的脚本或工具,实现对不同格式的文件的处理,比如说分析转换scss为css,或者把下一代的JS文件(ES6,ES7)转换为现代浏览器兼容的JS文件,对React的开发而言,合适的Loaders可以把React的中用到的JSX文件转换为JS文件。

    大家想了解更多的webpack的内容,可以参考webpack中文文档

    npm install css-loader babel-loader style-loader --save-dev

    然后我们在webpack.config.js中引用这些依赖,具体的格参数的意思,大家可以参考webpack各文档说明,我下面也会简单的注释一下。

    module.exports = {

    entry: './main.js', // webpack打包的入口文件

    output: {

    filename: './bundle.js' // 输出之后的文件名

    },

    module: {

    loaders: [

    {

    test: /\.jsx?$/,

    exclude: /node_modules/,

    loader: 'babel-loader' // babel的loader,jsx文件使用babel-loader处理

    }, {

    test: /\.css$/,

    exclude: /node_modules/,

    loader: 'style!css' // css和styleloader,对css后缀的文件进行处理

    }

    ]

    },

    devtool: 'cheap-source-map',

    }

  • 同时要让我们的 babel 能在 react中生效,同时支持es6,我们需要安装下面的插件

    npm install babel-preset-es2015 babel-preset-react babel-preset-stage-0 --save-dev

    安装完依赖后,我们在.babelrc文件中引入这几个依赖

    {

    "presets": ["es2015","react",'stage-0']

    }

  • 其次为了当我们每次添加list的时候有一个唯一的id,我们使用uuid

    npm install uuid --save-dev


四:组件的编写,是我们的页面能够显示出来

  • 编写模版文件index.html

    在这个模版文件里面,我们引入 semantic.css 文件,然后建立一个 id=app<div> 为了我们后续的 react 操作。

    <!DOCTYPE html>

    <html lang="en">

    <head>

    <meta charset="UTF-8">

    <title>react-todolist</title>

    <link rel="stylesheet" type="text/css" href="/css/semantic.css">

    <style>

    .active { color: red }

    .line{

    display: inline-block;

    border-bottom: 1px solid #222222;

    width:100px;

    position: absolute;

    left:0;

    top:7px;

    }

    .ui.comments .comment{

    padding:0;

    margin:2em 0 0;

    }

    </style>

    </head>

    <body>

    <div class="ui container" style="padding:30px;">

    <div id="app"></div>

    </div>

    <script src="./bundle.js"></script>

    </body>

    </html>

  • 编写入口文件main.js

    这边的data是我们的模拟数据,将其传入到<App/>组件,在子组件中可以通过props.data的方法获取 data。对于react的基础知识,大家可以参考来自一位react新手的react入门须知。

    import React from 'react'

    import ReactDOM from 'react-dom'

    import App from './app/component/App'

    let data = [

    {id: 0, text: '天气不错哦!!!', complete: false},

    {id: 1, text: '天气不错哦!!!', complete: false},

    {id: 2, text: '出去玩啊!!!', complete: true},

    ]

    ReactDOM.render(

    <App data={data}/>,

    document.getElementById('app')

    )

  • 编写component里面的组件

    1. App.js

      这个组件我们可以认为是一个容器组件,我们会把AppFormAppListAppFooter放在这个组件中。

      import React from 'react'

      import AppList from './AppList.js'

      import AppForm from './AppForm.js'

      import AppFooter from './AppFooter.js'

      class App extends React.Component {

      state = {

      choosevalue : 1,

      data: this.props.data

      }

      render () {

      const { data } = this.state;

      return (

      <div className='ui comments'>

      <h1>My Todo with React</h1>

      <div className='ui divider'></div>

      <AppForm />

      <AppList data={data}/>

      <AppFooter />

      </div>

      )

      }

      }

      export default App;

    2. AppForm.js

      这个组件是我们添加 list 用的一个form 组件,其中下面的styles这个对象那个也是jsx中申明样式的一种方式,我们还可以使用className来添加样式名字。

      import React from 'react';

      import uuid from 'uuid';

      var styles = {

      'title': {

      width: 200,

      display: 'inline-block',

      marginRight: 10,

      verticalAlign: 'top'

      }

      }

      class AppForm extends React.Component {

      render () {

      return (

      <form className='ui reply form'>

      <div className='field' style={styles.title}>

      <input type='text' placeholder='TODO' ref='text' />

      </div>

      <button type='submit' className='ui blue button'>

      添加

      </button>

      </form>

      )

      }

      }

      export default AppForm;

    3. AppList.js

      这个组件是我们在react中常说的智能组件,得到数据lists后通过 map 方法遍历数据,然后进行渲染。这里的map方法是用到了es6中的解构赋值,大家可以参考react新手必须懂得es6的基础知识,然后将值一一传递到子组件中去。

      import React from 'react'

      import AppTodos from './AppTodos'

      class AppList extends React.Component {

      render () {

      const a = this.props.data.map(({ id, text, complete }, index) => {

      return

      <AppTodos

      key={index}

      id={id}

      text={text}

      complete={complete}

      />

      })

      return (

      <div> { a } </div>

      )

      }

      }

      export default AppList;

    4. AppTodos.js

      这个组件是我们在react中常说的木偶组件,就是得到数据渲染组件。

      import React from 'react'

      var styles = {

      'title': {

      paddingLeft: '20px',

      paddingRight: '50px',

      position: 'relative'

      },

      'delete': {

      marginLeft: '20px',

      marginRight: '50px'

      }

      }

      class AppTodos extends React.Component {

      render () {

      return (

      <div className='comment'>

      <div className='content'>

      <span

      className='author'

      style={styles.title}

      >

      {this.props.text}

      <span

      className={this.props.complete ? 'line' : ''}

      />

      </span>

      <span className='author'

      style={styles.title}>

      {this.props.complete ? '已完成' : '未完成'}

      </span>

      <span className='author'>{this.props.id}</span>

      <span className='ui blue button'

      style={styles.delete} >

      删除

      </span>

      </div>

      </div>

      )

      }

      }

      export default AppTodos;

    5. AppFooter.js

      这个组件就是下面的三个按钮全部未完成已完成

      import React from 'react'

      var styles = {

      'title': {

      marginRight: 10,

      fontSize: 20

      },

      'top': {

      marginTop: 20

      }

      }

      class AppFooter extends React.Component {

      render () {

      return (

      <div>

      <h2 style={styles.top}>show</h2>

      <button

      type='submit'

      style={styles.top}

      className='ui blue button'

      value='1'

      ref='all'

      >

      全部

      </button>

      <button

      type='submit'

      style={styles.top}

      className='ui blue button'

      value='2'

      ref='active'

      >

      还未完成

      </button>

      <button

      type='submit'

      style={styles.top}

      className='ui blue button'

      value='3'

      ref='complete'

      >

      已完成

      </button>

      </div>

      )

      }

      }

      export default AppFooter;

    然后我们在命令行输入,会开启一个服务。

    npm run server

    打开浏览器,输入http://localhost:8080,可看到:

     

    react-demo_1.png


5,实现list的添加操作

  • 首先理一下流程

    首先在form输入待办事情,点击添加触发一个handleSubmit点击函数,但是我们的data是通过<App />组件来分发的,而list是组件AppList渲染的。这里涉及到了从子组件传递值给父组件,其实也很简单,就从父组件中传一个函数给子组件,子组件将值通过函数再传递出去,大家可以参考react父子组件间的交流。

  • 在组件App.js中,我们加入一个OnAddTodoItem函数,并传入到AppForm组件中,我们新建函数中将传进来的newItem通过concat()现在的data,然后更新state

      ...

    OnAddTodoItem (newItem) {

    let newdata = this.state.data.concat(newItem);

    this.setState({data : newdata});

    }

    render () {

    const { data } = this.state;

    return (

    <div className='ui comments'>

    <h1>My Todo with React</h1>

    <div className='ui divider'></div>

    <AppForm

    AddTodoItem={this.OnAddTodoItem.bind(this)} />

    <AppList

    data={data}/>

    <AppFooter />

    </div>

    )

    }

    }

    export default App;

  • 在组件AppForm.js中,我们加入一个handleSubmit函数,并在form表单添加一个onClick函数,将用户输入的数据,通过uuid生成的id、输入的text、以及是否完成false。通过函数传递给父组件。

    ...

    handleSubmit (event) {

    event.preventDefault()

    let text = this.refs.text.value

    if (!text.trim()) {

    alert("Input can't be null")

    return

    }

    let id = uuid();

    this.props.AddTodoItem({id,text,complete:false});

    }

    render () {

    return (

    <form

    className='ui reply form'

    onSubmit={this.handleSubmit.bind(this)}>

    <div

    className='field'

    style={styles.title}>

    <input type='text' placeholder='TODO' ref='text' />

    </div>

    <button type='submit' className='ui blue button'>

    添加

    </button>

    </form>

    )

    }

    }

    export default AppForm;

    你可以看到如下效果:

     

    react-add2.gif


6,完成筛选功能

  • 首先里一下流程

    我们给下面的三个按钮设置了不同的value1代表全部、2代表未完成、3代表已完成,然后我们根据相应的value,展示相应的list,给三个按钮分别加上handleAllhandleActivehandleComplete三个方法,在onClick时触发。

  • App.js

    添加一个加上choosevaluestate,默认为1,即全选,同时将其传入到<AppList/>中去,同时添加chooseValue的方法,然后传入到AppFooter组件中去。

    ...

    state = {

    choosevalue : 1,

    data: this.props.data

    }

    ChooseValue (id) {

    this.setState({choosevalue:id});

    }

    ...

    <AppList

    data={this.state.data}

    choosevalue={this.state.choosevalue}

    />

    <AppFooter

    SubmitChooseValue={this.ChooseValue.bind(this)}

    />

  • AppFooter.js

    ...

    handleAll () {

    let all = this.refs.all.value;

    this.props.SubmitChooseValue(all);

    }

    handleActive () {

    let active = this.refs.active.value;

    this.props.SubmitChooseValue(active);

    }

    handleComplete () {

    let complete = this.refs.complete.value

    this.props.SubmitChooseValue(complete);

    }

    render () {

    return (

    <div>

    <h2 style={styles.top}>show</h2>

    <button

    type='submit'

    style={styles.top}

    className='ui blue button'

    value='1'

    ref='all'

    onClick={this.handleAll.bind(this)}

    >

    全部

    </button>

    <button

    type='submit'

    style={styles.top}

    className='ui blue button'

    value='2'

    ref='active'

    onClick={this.handleActive.bind(this)}

    >

    还未完成

    </button>

    <button

    type='submit'

    style={styles.top}

    className='ui blue button'

    value='3'

    ref='complete'

    onClick={this.handleComplete.bind(this)}

    >

    已完成

    </button>

    </div>

    )

    }

    }

    export

以上是 react新手demo——TodoList 的全部内容, 来源链接: utcz.com/z/383961.html

回到顶部