参考文献
创建完成后,项目下面主要有public和src文件,前者是用来存放静态资源文件的,其中最主要的就是index.html文件,后者则是用来存放所有的react代码的 项目搭建好后,切换进项目,执行npm start命令,即可在本地localhost:3000窗口打开项目
运行完成后,我们可以页面看见效果 打开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文件,来设计一个表格组件,并将这个组件添加到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> ) } }保存查看页面,发现页面并没有什么变化,是一样的 所以所有组件都是可以相互嵌套的,而且简单组件和复杂组件也是可以相互嵌套的,并没有的区别
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} />弄好之后,保存查看页面结果
通过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] }) }转载于:https://www.cnblogs.com/zjh-study/p/10937847.html
相关资源:react最全项目实战