React -- 简易项目实战

参考文献

一、创建项目

npx create-react-app myTest

创建完成后,项目下面主要有publicsrc文件,前者是用来存放静态资源文件的,其中最主要的就是index.html文件,后者则是用来存放所有的react代码的
项目搭建好后,切换进项目,执行npm start命令,即可在本地localhost:3000窗口打开项目

二、修改app.js

运行完成后,我们可以页面看见效果
打开src文件夹,里面有个index.js和app.js文件,其中index.js是主入口文件,app.js就是页面展示建议react组件,现在修改一下app.js里面的东西,写入Hello React !,然后保存看看页面
书写代码有jsx和非jsx语法两种格式:
jsx

const h1 = <h1 class="app-title">Hello React !</h1>

no-jsx

const h1 = React.createElement('h1', {className: 'app-title'}, 'Hello React !')

三、创建Table.js

现在新建一个table.js文件,来设计一个表格组件,并将这个组件添加到app.js组件中
新建组件注意事项
1、Component作为一个组件引入了,不需要再执行React.Component
2、使用class继承,元素必须在render()方法里面返回
3、样式类名书写是className,不是class
4、一定要将组件导出export default componentName
5、react组件名必须大写字母开头
6、只能return一个根元素,不能return两个根元素,也就是说renturn的标签必须包裹在一个根标签里面,不能是两个同级标签

import React, { Component } from 'react'

class Table extends Component {
  render() {
    return (
      <table>
        <thead>
          <tr>
            <td>Name</td>
            <td>Job</td>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>李狗蛋</td>
            <td>程序猿</td>
          </tr>
          <tr>
            <td>王翠花</td>
            <td>攻城狮</td>
          </tr>
        </tbody>
      </table>
    )
  }
}
export default Table

组件写好后,在app.js里面引入组件并使用

import Table from './table.js'

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <h4>Hello React !</h4>
        <Table />
      </header>
    </div>
  );
}

然后保存查看页面

看起来样子有些丑,然后创建一个table.css文件,书写一些样式,让table美观一下,然后在table.js页面引入css文件

import './table.css'

然后保存查看页面

四、简单组件

其实通过class创建的组件可以称之为复杂组件,还可以创建简单组件,所谓的简单组件,其实用类似函数的方式声明组件,现在用简单组件把table的头部和躯体部分分别分离出来作为一个单独的小组件
简单组件跟复杂组件的区别之一就是简单组件不需要render()方法去置换一下return元素,直接返回react元素

// table.js
function TableHead(props) {
  return (
    <thead>
      <tr>
        <th>Name</th>
        <th>Job</th>
      </tr>
    </thead>
  )
}

function TableBody(props) {
  return (
    <tbody>
      <tr>
        <td>李狗蛋</td>
        <td>程序猿</td>
      </tr>
      <tr>
        <td>王翠花</td>
        <td>攻城狮</td>
      </tr>
    </tbody>
  )
}

调用

class Table extends Component {
  render() {
    return (
      <table>
        <TableHead />
        <TableBody />
      </table>
    )
  }
}

保存查看页面,发现页面并没有什么变化,是一样的

所以所有组件都是可以相互嵌套的,而且简单组件和复杂组件也是可以相互嵌套的,并没有的区别

五、组件通信props

react中组件通信跟vue有点类似,是通过props来接收数据传递,不同的是:
1、数据是全局保存在props对象里面的,直接调用props对象就可以获取
2、数据传递也不需要通过v-bind来绑定参数,直接写即可,只不过传入参数使用{}包裹,而不是""
3、在简单函数里,props是作为一个参数传入的,所以直接通过props.key获取,但是在class里面,props是继承于Compoent,需要通过super()方法,调用是通过this.props.key
因为所有组件都是在app.js里面渲染的,所以现在要在app.js里面创建数据传递过去,需要注意一点就是传递的数据必须创建在渲染组件元素的render()函数里面,创建在render()方法之外,是没有效果的,如果是简单组件,就直接声明一个数据数组
数据声明好之后,直接在组件上传递

function App() {
  const Head = [
    { header: 'Name' },
    {header: 'Job'}
  ]
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <h4>Hello React !</h4>
        // 传递数据
        <Table Head={Head} />
      </header>
    </div>
  );
}

接下来就可以在Table组件的render函数通过es6方法从props里面拿到数据赋值给新声明的变量,注意必须在render()方法里面声明获取,简单函数直接声明获取获取

class Table extends Component {
  render() {
    // 拿取元素
    const {Head} = this.props
    return (
      <table>
        <TableHead Head={Head} />
        <TableBody />
      </table>
    )
  }
}

接下里就是列表渲染表格头部了,注意react里面列表渲染时通过map()方法实现的,因为map()方法返回的是一个结果数组
需要注意的是每一个循环创建的react元素必须赋予一个key值,这是唯一标识符,同一个react元素里不能相同

const TableHead = (props) => {
  const myHead = props.Head.map((item, index) => {
    return <th key={index}>{item.header}</th>
  })
  return (
    <thead>
      <tr>
        {myHead}
      </tr>
    </thead>
  )
}

然后保存查看页面,发现页面结构数据并没有变化,也没有报错

同理我们可以把body数据也可以赋予过去

const Body = [
    {
      name: '李狗蛋',
      job: '程序猿',
    },
    {
      name: '王翠花',
      job: '攻城狮',
    },
    {
      name: '二狗子',
      job: '加班狗',
    }
  ]
<Table Head={Head} Body={Body} />

弄好之后,保存查看页面结果

六、数据修改state

通过props可以传递数据,但是这个数据传过去后是不可变的,无法进行操作,所以需要通过state来声明数据,这样数据就可以通过this.setState()方法来进行相关操作
现在我们创建一个state对象,把先前的数据全部移到这个对象里面

const state = {
    Head: [
      { header: 'Name' },
      {header: 'Job'}
    ],
    Body: [
      {
        name: '李狗蛋',
        job: '程序猿',
      },
      {
        name: '王翠花',
        job: '攻城狮',
      },
      {
        name: '二狗子',
        job: '加班狗',
      }
    ]
  }

在Table组件依然是通过this.props获取这个数据
现在我们需要操作这个数组,来进行数组的内容的添加和删除,首先我们执行删除操作,在app.js声明一个删除数据的方法,用来执行删除,这个方法是根据index来删除
删除函数

removeTr = index => {
    const { Body } = this.state
    this.setState({
      Body: Body.filter((item, ind) => {
        return ind !== index
      })
    })
  }

弄好之后,把数据通过props传递过去,然后回到Table组件,在body里面新增一行,执行方法

function TableBody(props) {
  const myBody = props.Body.map((item, index) => {
    return <tr key={index}>
      <td>{item.name}</td>
      <td>{item.job}</td>
      <td>
        <button onClick={() => props.removeTr(index)}>Delete</button>
      </td>
  </tr>
  })
  return (
    <tbody>
      {myBody}
    </tbody>
  )
}

注意
这里踩了一个坑,通过事件执行方法时,一定要通过一个函数去执行props里传过来的方法,否则好像会自动执行
这样我们点击删除按钮,就会将当前的数组索引作为参数传过去,然后通过filter()方法过滤掉index相同的数组项,返回其他数组项,实现删除效果

七、新增数据

在做逻辑操作之前,我们需要新建一个新增数据的表单组件
Form.js

import React, { Component } from 'react'

class Form extends Component {
  constructor(props) {
    super(props)
    // 初始化input的value值
    this.initValue = {
      name: '',
      job: '',
    }
    // 将初始化值赋值给state
    this.state = this.initValue
  }
  // input标签内容改变时执行
  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value,
    })
  }
  // 点击提交按钮时执行的操作
  submitForm = () => {
    // 这个方法是app.js那边传过来的,这个需要把用户输入的数据传过去
    this.props.handleSubmit(this.state)
    // 重置input的value值
    this.setState(this.initValue)
  }
  render() {
    const {name, job} = this.state
    return (
      <form>
        <label>
          Name:
        </label>
        <input type="text" value={name} name="name" onChange={this.handleChange} /><br />
        <label>
          Job:
        </label>
        <input type="text" value={job} name="job" onChange={this.handleChange} /><br />
        <input type="button" value="新增" onClick={this.submitForm} />
      </form>
    )
  }
  }

app.js

handleSubmit = (valObj) => {
    // 通过解构的方式,把传过来的数据添加到Body数组里,
    this.setState({
      Body: [...this.state.Body, valObj]
    })
  }

猜你喜欢

转载自www.cnblogs.com/zjh-study/p/10937847.html
今日推荐