react入门系列之使用create-react-app搭建一个todolist-dome

安装create-react-app脚手架

  • npm install -g create-react-app

创建你的todo-list项目

  • create-react-app todo-list

  • 注意npm命名限制,项目名称不能含有大写字母。

清除项目中不必要的文件

  • src目录中的:App.css, App.test.js, logo.svg, serviceWorker.js文件

  • public目录中的: manifest.json文件

  • 其中manifest.json,serviceWorker.js属于pwa的配置文件,有兴趣可以了解一下。

  • pwa 让网页写好以后,用户访问了一次之后,就可以把我们的网页当作app来用,可以不用联网。

  • 在手机上或者电脑桌面上通过点击快捷方式来打开页面。

  • 他的图标和快捷方式是通过public中manifest.json去定义的

之前删除的文件在剩下的文件有引入使用,现在将其删除

  • App.js删除下列代码注释部分

import React, { Component }from 'react';

// import logo from './logo.svg';

// import './App.css';

class App extends Component {

  render(){

    return (

      {

        /*

      
logo

Edit src/App.js and save to reload.

Learn React
*/ }
hello react
); } } export default App;
  • index.js 删除一下注释部分

import React from 'react';

import ReactDOM from 'react-dom';

// import './index.css';

import App from './App';

//import * as serviceWorker from './serviceWorker'; // pwa 引入

ReactDOM.render(, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change

// unregister() to register() below. Note this comes with some pitfalls.

// Learn more about service workers: https://bit.ly/CRA-PWA

// serviceWorker.unregister(); // pwa 使用

  • public中的index.html文件,删除以下注释部分代码





  

    

    

    

    

    

    

    

    

    

    todo-list 

  

  

    

    

项目目录解析

  • yarn.lock -- 包锁文件

  • README.MD -- 项目介绍

  • package.json -- node的包文件

  • .gitignore -- 使用git的时候可以将不想上传到git的文件在此处标记

  • node_modules -- 项目依赖包

  • index.html 项目首页模版

  • favicon.ico 网页图标

  • index.js 入口js文件

  • app.js 万年老二组件

jsx语法

  • jsx语法规定,在return中的最外层只能含有一个标签。

  • 为此你可以使用div也可以使用react提供的Fragment占位符,他其实也是一个组件。

  • 在js中写html标签。就称为jsx语法

  • render()函数中return => html标签或者组件名加括号,组件必须以大写字母开头

  • jsx中使用变量,需要使用{}包裹

  • 现在我们将App.js改造成如下代码。

  • 通过npm run start 启动你的项目


    import React, { Component, Fragment } from 'react';

    class App extends Component {

      render(){

        return (

          

            
  • react
); } } export default App;

react的响应式思想和事件绑定

定义数据

  • 之前我们已经将todo-list的结构搭好了。现在需要实现功能。

  • 不要直接操作dom

  • 通过改变数据改变dom

  • 此时我们需要准备两组数据,1组数据存储input里面的值,1组数据存储列表中的值。

  • 如何定义数据?

    • 一个类必定有一个构造函数,并且他是最先执行的函数,我们可以将数据存在这个构造函数中

    • constructor 即为App类的构造函数,构造函数中有state属性,他是用来存放这个类的变量的。

    • 因此数据就定义在state中。

    • constructor 构造函数还有一个super()方法,他可以帮助App类调用他的父类(Component)的属性。

  • 使用箭头函数不然this指向出错

  • 只能通过setState方法去改变state中的变量

  • 代码如下


    import React, { Component, Fragment }from 'react';

    class App extends Component {

      constructor(props){

        super(props);

        this.state = {

          inputValue: '',// 用来存储 input框中的 value值。

          list:[] // 用来存储 每一个li的 value值。

        }

      }

      render(){

        return (

          

          
  • react
); } } export default App;

绑定数据

  • 我们上面已经定义好了数据,现在将数据绑定到对应的dom上

  • 这样方便我们通过数据改变dom

  • react jsx语法中,绑定数据到dom上,使用{} 包裹。 -- value = {this.state.inputValue}

  • 列表数据绑定也是一样,在{}中写js表达式,我们可以通过es5的map函数遍历list数组获得item值,和他的下标

  • 然后通过return返回一个li标签,返回之前,将item绑定到li的value值,将index作为li的key

  • 注意的是,实际开发中将index作为key值是一个错误的做法。


    import React, { Component, Fragment }from 'react';

    class App extends Component {

      constructor(props){

        super(props);

        this.state = {

          inputValue: '',// 用来存储 input框中的 value值。

          list:['西瓜','苹果'] // 用来存储 每一个li的 value值。

        }

      }

      render(){

        return (

          

          
    { this.state.list.map((item, index) => { return (
  • {item}
  • ) }) }
); } } export default App;

react的事件绑定

  • 我们现在需要绑定input的onChange事件,以此达到input的value值的变化和我们数据inputValue变化一致

  • react的事件绑定和原生的区别就是第二个单词首字母要大写,onChang

  • 在onChange事件中绑定handleInputChange()方法,传入事件对象,获取target值,他的value就是当前input的value值

  • 再通过this.setState()方法区改变组件中inputValue的值。

  • 要注意的是,react中只能通过setState方法改变state中的属性。


      import React, { Component, Fragment }from 'react';

    class App extends Component {

      constructor(props){

        super(props);

        this.state = {

          inputValue: '',// 用来存储 input框中的 value值。

          list:['西瓜','苹果'] // 用来存储 每一个li的 value值。

        }

      }

      handleInputChange = (e) => {

        this.setState({

          inputValue: e.target.value

        })

        console.log(e.target)

      }

      render(){

        return (

          

          
    { this.state.list.map((item, index) => { return (
  • {item}
  • ) }) }
); } } export default App;

如何实现Todolis的增删功能

  • 增加思路 在input框中输入要添加的字段,点击提交,提交绑定一个方法,将inputValue的值添加到list数组中

  • 删除思路 在每一个li中绑定点击事件,在点击的时候,传入当前li的下标,在事件方法中通过下标删除list中的对应元素

  • 要注意的时,在传入index的时候我尝试过直接在方法名后面传入,但是会报错,改在bind()方法中第二个参数传入,就没有问题了

  • state中的属性数据,只能通过this.setState({})方法修改,不能直接修改。

  • 在使用splice的时候踩了一个坑,list = list.splice(index, 1)

  • 这是一行错误代码,这样赋值,list等于是你删除的哪个元素组成的数组,splice会改变原数组,返回被删除的数组。无需再赋值


    import React, { Component, Fragment } from 'react';

    class App extends Component {

      // 定义数据,一个类必定有一个构造函数,他是最先执行的函数

      constructor(props){

        super(props); // App继承Component类,所以要通过super(props)调用他的父类的属性

        this.state = {

          inputValue: '', // input框的value

          list: [] // 列表的数据

        }

      }

      handleInputChange = (e) => { // 使用箭头函数不然this指向出错

        this.setState({ // 只能通过setState去改变state中的变量

          inputValue : e.target.value

        })

        console.log(e.target)

      }

      // 增加方法

      handleBtnClick = () => {

        this.setState({

          list : [...this.state.list, this.state.inputValue],

          inputValue: ''

        })

      }

      // 删除方法

      handleItemDelet = (index) => {

        console.log(index)

        let list = [...this.state.list];

        // list = list.splice(index, 1) // 这是一行错误代码,这样赋值,list等于是你删除的哪个元素组成的数组

        list.splice(index, 1)

        console.log(list)

        this.setState({

          list : [...list]

        })

      }

      render(){

        return (

          

            
    { this.state.list.map((item, index) => { return
  • {item}
  • // 实际编程之中使用index做key值是一个非常不好的习惯 }) }
); } } export default App;

jsx细节补充

  • 注释用大括号包裹,单行注释要换行

  • 添加样式使用 className ,class会被解析成类

  • dangerouslySetInnerHTML = {js表达式}

  • dangerouslySetInnerHTML = {{ __html: item }} 多一个花括号表示一个js对象

  • // 如果需要显示input框中内容中的标签效果 就这么写。但是这样写容易造成xss攻击 对应的标签中就不需要写item了

  • lable标签 使用htmlFor引入到指定标签中


  render(){

    return (

      {/* 他其实是一个组件 */ }

        
输入内容
    { this.state.list.map((item, index) => { return (
  • ) // 实际编程之中使用index做key值是一个非常不好的习惯 }) }
); }

你可能感兴趣的:(react入门系列之使用create-react-app搭建一个todolist-dome)