使用場景,在一個列表中,點擊每一行會彈出一個表單,通過修改表單數據並提交來修改這一行的數據,其中某個數據的填寫需要通過Mention實現動態提示及自動補全的功能。
具體效果為:



遇到的問題:
1、希望所需要的提示和自動補全的內容不同,實際場景類似於ide中函數提示(包含參數和返回值以及用法等提示)和函數補全(只補全函數名)的功能。
Ant Design的Mention組件提供了Nav可以實現這個功能,但是實際使用中發現會報錯,經查發現為Ant Design的一個bug,升級版本解決。
2、然后遇到問題,發現suggestions使用了Nav數組之后,不能通過輸入自動動態查詢,具體表現為

經查原因為,將生成suggestions的計算寫到了引用Mention的地方:
const suggestions = [ {children:'張三 男 18 會計', value:'張三'}, {children:'李四 女 21 審計', value:'李四'}, {children:'王五 男 33 總監', value:'王五'} ] <Mention style={{ width: '100%' }} suggestions={ suggestions.map( (x) => <Nav {...x} />) } />
解決方法,將計算過程提到外面去……
3、點擊不同數據行的時候,彈出表單數據不更新,也就是表單的 initialValue 不生效
在 react 生命周期 componentWillReceiveProps(nextProps) 中把 Mention 的數據更新。
需要注意的地方是 Mention 的 value 不是 string,需要在多處通過 toString 和 toContentState 進行轉換。
行吧,困擾了兩天的bug好像寫出來也沒什么東西……QAQ怪我蠢……
完整代碼:
import React from 'react'; import { Table, Icon, Button, Form, Input, Modal, Mention } from 'antd'; const FormItem = Form.Item; const { toString, toContentState, Nav } = Mention; const suggestions = [ <Nav children='張三 男 18 會計' value='張三' />, <Nav children='李四 女 21 審計' value='李四' />, <Nav children='王五 男 33 總監' value='王五' /> ] class EditForm extends React.Component { onSave = () => { this.props.form.validateFields((err, values) => { if (!err) { this.props.onSave({ ...values, person: toString(values.person) }) this.props.form.resetFields() this.props.form.setFieldsValue({person: toContentState('')}) console.log(toString(this.props.form.getFieldValue('person'))) } }); } onCancel = () => { this.props.onCancel() // 重置為初始值 initialValue 防止點擊不同區域出現數據不刷新的情況(although...i dont know why... this.props.form.resetFields() } // 在接受 props 時調用 無論 nextProps 和 this.props 是否相等 // 首先要在表單隱藏變為顯示的時候賦值 其次 只有當前已經存在顯示值的時候才調用 否則沒意義 也會存在 getFiledsValue 未注冊情況 componentWillReceiveProps(nextProps) { if (nextProps.visible === true && this.props.visible === false && this.props.record) { this.props.form.setFieldsValue({person: toContentState(nextProps.record.person)}) } } render() { // console.log(this.props) const { record, visible, onCancel } = this.props; if (!record) return null; const { getFieldDecorator } = this.props.form; return ( <Modal visible={visible} title="編輯事件" okText="保存" onCancel={this.onCancel} onOk={this.onSave} > <Form layout="vertical" onSubmit={this.handleSubmit}> <FormItem> {getFieldDecorator('event', { rules: [{ required: true, message: '請輸入事件!' }], initialValue: record.event })( <Input /> )} </FormItem> <FormItem> {getFieldDecorator('person', { initialValue: toContentState(record.person), rules: [{ required: true, message: '請輸入相關人員!' }], })( <Mention style={{ width: '100%' }} suggestions={ suggestions } /> )} </FormItem> </Form> </Modal> ); } } const WrappedEditForm = Form.create()(EditForm); class EventTable extends React.Component { state = { visible: false, record: null, index: 0 } columns = [ { title: '操作', key: 'action', render: (text, record, index) => <div> <Button onClick={()=>{ this.setState({ visible: true, record, index }) }}>編輯</Button> </div>, width: 200 }, { title: '事件', dataIndex: 'event', key: 'event', render: (text, record, index) => <div> <span>{text}</span> </div>, width: 200 }, { title: '相關人員', dataIndex: 'person', key: 'person', width: 200 } ]; data = [ { key: '1', event: '早餐', person: '@組長', }, { key: '2', event: '午餐', person: '@組長', }, { key: '3', event: '晚餐', person: '@組長', } ]; onCancel = () => { this.setState({visible: false}) } onSave = (values) => { this.setState({visible: false}) this.data[this.state.index].event = values.event this.data[this.state.index].person = values.person } render() { return ( <div> <Table columns={this.columns} dataSource={this.data} style={{ width: 600 }}/> <WrappedEditForm visible={this.state.visible} record={this.state.record} onCancel={this.onCancel} onSave={this.onSave} /> </div> ) } } export default EventTable
