二、React组件化
发布时间:2020-12-15 09:30:10 所属栏目:百科 来源:网络整理
导读:使用第三方组件 安装:npm install antd --save 试用 ant-design 组件库 import React,{ Component } from ‘react‘ import Button from ‘antd/lib/button‘ ; import ‘antd/dist/antd.css‘ export default class TestAntd extends Component { render()
使用第三方组件安装:npm install antd --save 试用 ant-design 组件库 import React,{ Component } from ‘react‘
import Button from ‘antd/lib/button‘; import ‘antd/dist/antd.css‘ export default class TestAntd extends Component { render() { return ( <div> <Button type="primary">Button</Button> </div> ) } }
上面 import 的内容太长,不利于日常开发 配置按需加载安装 react-app-rewired 取代 react-scripts,可以扩展webpack的配置,类似 vue.config.js npm install react-app-rewired customize-cra babel-plugin-import -D // 根目录创建 config-overrides.js
const { override,fixBabelImports,addDecoratorsLegacy } = require("customize-cra")
module.exports = override( fixBabelImports("import",{ libraryName: "antd",libraryDirectory: "es",style: "css" }),addDecoratorsLegacy() // 配置装饰器,这里如果配置,需要先安装下面的npm )
修改package.json "scripts": {
"start": "react-app-rewired start","build": "react-app-rewired build","test": "react-app-rewired test","eject": "react-app-rewired eject" }
? 支持装饰器配置 npm install -D @babel/plugin-proposal-decorators ? 例如:高级组件链式调用 import React,{ Component } from ‘react‘
const foo = Cmp => props => { return <div style={{border: ‘1px solid red‘}}> <Cmp {...props}/> </div> } const foo2 = Cmp => props => { return <div style={{border: ‘1px solid green‘,padding: ‘10px‘}}> <Cmp {...props}/> </div> } function Child(props){ return <div>Child</div> } export default class HocPage extends Component { render() { const Foo = foo2(foo(Child)) return ( <div> <h1>HocPage</h1> <Foo /> </div> ) } }
改为装饰器的写法:装饰器只能用于装饰 class 组件 import React,padding: ‘10px‘}}> <Cmp {...props}/> </div> } @foo2 @foo class Child extends Component { render(){ return <div>Child</div> } } export default class HocPage extends Component { render() { return ( <div> <h1>HocPage</h1> <Child /> </div> ) } }
? 注意:需要引入 antd样式文件:?import?‘antd/dist/antd.css‘; 使用antd的Form表单 import React,{ Component } from ‘react‘
import {Form,Input,Icon,Button} from ‘antd‘ const FormItem = Form.Item export default class FormPage extends Component { constructor(props){ super(props) this.state = { name: ‘‘,password: ‘‘ } } change = (field,event)=>{ this.setState({ [field]: event.target.value }) } submit = ()=>{ console.log(‘state‘,this.state); } render() { return ( <div> <h1>FormPage</h1> <Form> <FormItem label="姓名"> <Input prefix={<Icon type="user"/>} onChange={event => this.change(‘name‘,event)}/> </FormItem> <FormItem label="密码"> <Input type="password" prefix={<Icon type="lock"/>} onChange={event => this.change(‘password‘,event)}/> </FormItem> <FormItem> <Button type="primary" onClick={this.submit}>提交</Button> </FormItem> </Form> </div> ) } }
Form中内容的使用? ---? Form.create() import React,{Component} from ‘react‘
import {Form,Button} from ‘antd‘ const FormItem = Form.Item class FormPageDecorators extends Component { submit = () => { const { getFieldsValue,getFieldValue } = this.props.form // 获取所有Field的值 console.log(‘submit‘,getFieldsValue()); // 获取单个值 console.log(‘submitName‘,getFieldValue(‘name‘)); } render() { // 装饰器 const {getFieldDecorator} = this.props.form console.log(this.props.form); return ( <div> <h1>FormPageDecorators</h1> <Form> <FormItem label="姓名"> { getFieldDecorator(‘name‘)(<Input prefix={< Icon type = "user" />}/> )} </FormItem> <FormItem label="密码"> { getFieldDecorator(‘password‘)(<Input type="password" prefix={< Icon type = "lock" />}/> )} </FormItem> <FormItem> <Button type="primary" onClick={this.submit}>提交</Button> </FormItem> </Form> </div> ) } } export default Form.create()(FormPageDecorators)
表单验证 // 校验规则
const nameRule = {
required: true,message: ‘please input your name‘ } const passwordRule = { required: true,message: ‘please input your password‘ } class FormPageDecorators extends Component { submit = () => { const { validateFields } = this.props.form // 表单验证 validateFields((err,values)=>{ if(err){ console.log(‘err:‘,err) }else{ console.log(‘submit:‘,values); } }) } } <FormItem label="姓名"> { getFieldDecorator(‘name‘,{rules: [nameRule]})(<Input prefix={< Icon type = "user" />}/> )} </FormItem> <FormItem label="密码"> { getFieldDecorator(‘password‘,{rules: [passwordRule]})(<Input type="password" prefix={< Icon type = "lock" />}/> )} </FormItem>
? 自己写一个Form.create() import React,{ Component } from ‘react‘ function kFormCreate(Cmp){ return class extends Component { constructor(props){ super(props) this.options = {} // 配置字段项 this.state = {} // 存字段值 } handleChange = (event)=>{ const {name,value} = event.target this.setState({ [name]: value }) } getFieldDecorator = (field,options)=>{ this.options[field] = options return InputCmp=>( <div className="border"> {React.cloneElement(InputCmp,{ name: field,value: this.state[field] || "",onChange: this.handleChange })} </div> ) } getFieldsValue = ()=>{ return {...this.state} } getFieldValue = (field)=>{ return this.state[field] } validateFields = (callback)=>{ const tem = {...this.state} const err = [] for(let i in this.options){ if(tem[i] === undefined){ err.push({ [i]: ‘error‘ }) } } if(err.length>0){ callback(err,tem) }else{ callback(undefined,tem) } } render(){ return ( <div className="border"> <Cmp {...this.props} getFieldDecorator={this.getFieldDecorator} getFieldsValue={this.getFieldsValue} getFieldValue={this.getFieldValue} validateFields={this.validateFields} /> </div> ) } } } // 校验规则 const nameRule = { required: true,message: ‘please input your name‘ } const passwordRule = { required: true,message: ‘please input your password‘ } class MyFormPage extends Component { submit = ()=>{ const {getFieldsValue,getFieldValue,validateFields} = this.props validateFields((err,values)=>{ if(err){ console.log(‘err‘,err); }else{ console.log(‘submitSuccess:‘,values); } }) } render() { const {getFieldDecorator} = this.props return ( <div> <h1>MyFormPage</h1> { getFieldDecorator(‘name‘,{rules: [nameRule]})( <input type="text"/> ) } { getFieldDecorator(‘password‘,{rules: [passwordRule]})( <input type="password"/> ) } <button onClick={this.submit}>提交</button> </div> ) } } export default kFormCreate(MyFormPage) ? ? Dialog组件(弹窗组件)Dialog.js import React,{ Component } from ‘react‘ import {createPortal} from ‘react-dom‘; export default class Dialog extends Component { constructor(props){ super(props) const doc = window.document this.node = doc.createElement(‘div‘) doc.body.appendChild(this.node) } componentWillUnmount(){ window.document.body.removeChild(this.node) } render() { return createPortal( <div className="dialog"> <h1>Dialog</h1> </div>,this.node ) } } DialogPage.js import React,{ Component } from ‘react‘ import {Button} from ‘antd‘; import Dialog from ‘../components/Dialog‘; export default class DialogPage extends Component { constructor(props){ super(props) this.state = { showDialog: false } } handleShowDialog = ()=>{ this.setState({ showDialog: !this.state.showDialog }) } render() { const {showDialog} = this.state return ( <div> <h1>DialogPage</h1> <Button onClick={this.handleShowDialog}>dialog toggle</Button> { showDialog && <Dialog /> } </div> ) } } ? 树形组件css文件 .tri { width: 20px; height: 20px; margin-right: 2px; padding-right: 4px; } .tri-close:after,.tri-open:after { content: ""; display: inline-block; width: 0; height: 0; border-top: 6px solid transparent; border-left: 8px solid black; border-bottom: 6px solid transparent; } .tri-open:after { transform: rotate(90deg); } TreeNode.js import React,{ Component } from ‘react‘ import classnames from ‘classnames‘; export default class TreeNode extends Component { constructor(props){ super(props) this.state = { expanded: false } } handleExpanded = ()=>{ this.setState({ expanded: !this.state.expanded }) } render() { const {title,children} = this.props.data const {expanded} = this.state const hasChildren = children && children.length > 0 return ( <div> <div className="nodesInner" onClick={this.handleExpanded}> { hasChildren && <i className={classnames("tri",expanded ? ‘tri-open‘:‘tri-close‘)}></i> } <span>{title}</span> </div> { hasChildren && expanded && <div className="children"> { children.map(item=>{ return <TreeNode key={item.key} data={item}/> }) } </div> } </div> ) } } TreePage.js import React,{ Component } from ‘react‘ import TreeNode from ‘../components/TreeNode‘; //数据源 const treeData = { key: 0,//标识唯?一性 title: "全国",//节点名称显示 children: [ //?子节点数组 { key: 6,title: "北方区域",children: [{ key: 1,title: "?龙江省",children: [{ key: 6,title: "哈尔滨",},],{ key: 2,title: "北京",{ key: 3,title: "南方区域",children: [{ key: 4,title: "上?",{ key: 5,title: "深圳",}; export default class TreePage extends Component { render() { return ( <div> <h1> TreePage </h1> <TreeNode data={treeData}/> </div> ) } } ? 常见组件优化技术 定制组件的 shouldComponentUpdate 钩子 import React,{ Component } from ‘react‘ export default class CommentList extends Component { constructor(props){ super(props) this.state = { comments: [] } } componentDidMount(){ setInterval(() => { this.setState({ comments: [{ author: "?明",body: "这是小明写的?文章",{ author: "小红",body: "这是小红写的?文章",}] }) },1000); } render() { const {comments} = this.state return ( <div> <h1>CommentList</h1> { comments.map(item=>{ return <Comment key={item.author} data={item}/> }) } </div> ) } } class Comment extends Component{ shouldComponentUpdate(nextProps,nextState){ const {author,body} = nextProps const {author: nowAuthor,body: nowBody} = nextProps if(author===nowAuthor && body === nowBody) { return false } } render(){ const {author,body} = this.props.data console.log(‘render‘); return <div className="border"> <p>作者: {author}</p> <p>内容: {body}</p> </div> } } ? PureComponent import React,{ Component,PureComponent } from ‘react‘ export default class PureConponentPage extends Component { constructor(props){ super(props) this.state = { counter: 0 } } setCounter = ()=>{ this.setState({ counter: 1 }) } render() { const {counter} = this.state return ( <div> <h1>PureConponentPage</h1> <button onClick={this.setCounter}>change</button> <Demo counter={counter}/> </div> ) } } class Demo extends PureComponent{ render(){ const {counter} = this.props console.log(‘render‘); return <div> {counter} </div> } } 缺点是必须要用 class 形式,而且要注意是浅比较 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |