react实现一个表格内容添加到文本的编辑器

react实现一个表格内容添加到文本的编辑器

技术攻克难点

一.输入框的值修改(onChange)

二.dangerouslySetInnerHTML的使用

1.dangerouslySetInnerHTMl 是React标签的一个属性,类似于angular的ng-bind;

2.有2个{{}},第一{}代表jsx语法开始,第二个是代表dangerouslySetInnerHTML接收的是一个对象键值对;

3.既可以插入DOM,又可以插入字符串;

4.不合时宜的使用 innerHTML 可能会导致 cross-site scripting (XSS) 攻击。 净化用户的输入来显示的时候,经常会出现错误,不合适的净化也是导致网页攻击的原因之一。dangerouslySetInnerHTML 这个 prop 的命名是故意这么设计的,以此来警告,它的 prop 值( 一个对象而不是字符串 )应该被用来表明净化后的数据。

代码实现

/*
@返回文本的实例
{
"key": 0,
"result": "<div><span style=\"color:red\">你好</span><span style=\"color:red\">你好</span></div>",
"text": "你好你好你好你好你好你好你好你好"
},
*/
import 'moment/locale/zh-cn';
import locale from 'antd/es/date-picker/locale/zh_CN';
import React, { Component } from 'react';
import axios from 'axios';
import utils from "../../utils"
import { Input, Button, DatePicker, Space, Table, Row ,Col} from 'antd';


import './index.less'
const { TextArea } = Input;
let path = window.location.pathname.split('/')[1], search, url
if (window.location.search) {
    search = window.location.search
    const s = search.substr(1, search.length).split('&')
    const m = s[0].split('=')
    url = `http://nlpai.woa.com/${m[1]}/`
} else {
    url = `http://nlpai.woa.com/${path}/end/`
}
export default class TopicCards extends Component {
    constructor(props) {
        super(props);
        this.textInput = React.createRef();
        this.state = {
            data: [
            ],
            list:[],
            isLoaded: false,
            value:''
        }
    }
    // 向后台发送请求
    async getRequest (value) {
        console.log(this.state.timeInterval)
        if (value) {
            const _this = this;
            utils.post({
                url:`http://*****(项目路径保密)`,
                data:{
                    "query":value
                }
            }).then(res => {
                console.log(res)
                this.setState({
                    data:res
                })
            })
            
        } else {
            alert('请正确填写openid或微信号')
        }
    }
    // 展示表格
    showTable () {
        const columns = [
            {
                title: 'right',
                dataIndex: 'result',
                key: '0',
                render:(result)=>{
                    return <div dangerouslySetInnerHTML={{ __html: result.replace('script','') }}></div>
                }
            }
        ];
        return (
            <Table columns={columns} dataSource={this.state.data} scroll={{ y: 900 }} pagination={false} 
                onRow={record => {
                    return {
                        onClick: event => {this.addList(record.text)}, // 点击行
                    };
                }} />
        )
    }

    // 添加的表格
    addList(value){
        console.log(value)
        const v=this.state.value
        this.setState({
            value:v+value+'\n'
        })
    }
    onChange = ({ target: { value } }) => {
        this.setState({ value });
    };
    render () {
        
        return (
            <div className="rightToLeft">
                <h1>弹幕检索 </h1>
                {/*搜索*/}
                <div className="search">
                    <Input size="large" style={{ width: 400 }} placeholder="请搜索" ref={this.textInput} onPressEnter={()=>{this.getRequest(this.textInput.current.state.value)}} />&emsp;
                    <Button type="primary" size="large" onClick={() => {
                        this.getRequest(this.textInput.current.state.value)
                    }}>查询</Button>&emsp;
                </div>
                <div className="tables">         
                    <div className="left">
                        <TextArea rows={4} allowClear value={this.state.value}  onChange={this.onChange} autoSize={{ minRows: 24, maxRows: 44 } }/>
                    </div>
                    <div className="right">
                        {this.showTable()}
                    </div>
                    
                </div>
            </div>
        )


    }
}

效果图如下:
在这里插入图片描述
另附antd表格编辑组件封装jsx

import React, { useContext, useState, useEffect, useRef } from 'react';
import { Table, Input, Button, Popconfirm, Form } from 'antd';
const EditableContext = React.createContext();

const EditableRow = ({ index, ...props }) => {
    const [form] = Form.useForm();
    return (
        <Form form={form} component={false}>
            <EditableContext.Provider value={form}>
                <tr {...props} />
            </EditableContext.Provider>
        </Form>
    );
};

const EditableCell = ({
    title,
    editable,
    children,
    dataIndex,
    record,
    handleSave,
    ...restProps
}) => {
    const [editing, setEditing] = useState(false);
    const inputRef = useRef();
    const form = useContext(EditableContext);
    useEffect(() => {
        if (editing) {
            inputRef.current.focus();
        }
    }, [editing]);

    const toggleEdit = () => {
        setEditing(!editing);
        form.setFieldsValue({
            [dataIndex]: record[dataIndex],
        });
    };

    const save = async (e) => {
        try {
            const values = await form.validateFields();
            toggleEdit();
            handleSave({ ...record, ...values });
        } catch (errInfo) {
            console.log('Save failed:', errInfo);
        }
    };

    let childNode = children;

    if (editable) {
        childNode = editing ? (
            <Form.Item
                style={{
                    margin: 0,
                }}
                name={dataIndex}
                rules={[
                    {
                        required: true,
                        message: `${title} is required.`,
                    },
                ]}
            >
                <Input ref={inputRef} onPressEnter={save} onBlur={save} />
            </Form.Item>
        ) : (
            <div
                className="editable-cell-value-wrap"
                style={{
                    paddingRight: 24,
                }}
                onClick={toggleEdit}
            >
                {children}
            </div>
        );
    }

    return <td {...restProps}>{childNode}</td>;
};

class EditableTable extends React.Component {
    constructor(props) {
        super(props);
        this.columns = [
            {
                title: 'name',
                dataIndex: 'name',
                width: '30%',
                editable: true,
            },
        ];
        this.state = {
            dataSource: [
                {
                    key: '0',
                    name: 'Edward King 0',
                    age: '32',
                    address: 'London, Park Lane no. 0',
                },
                {
                    key: '1',
                    name: 'Edward King 1',
                    age: '32',
                    address: 'London, Park Lane no. 1',
                },
            ],
        };
    }

    handleSave = (row) => {
        const newData = [...this.state.dataSource];
        const index = newData.findIndex((item) => row.key === item.key);
        const item = newData[index];
        newData.splice(index, 1, { ...item, ...row });
        this.setState({
            dataSource: newData,
        });
    };

    render() {
        console.log(this.props.lists)
        const { dataSource } = this.state;
        const components = {
            body: {
                row: EditableRow,
                cell: EditableCell,
            },
        };
        const columns = this.columns.map((col) => {
            if (!col.editable) {
                return col;
            }

            return {
                ...col,
                onCell: (record) => ({
                    record,
                    editable: col.editable,
                    dataIndex: col.dataIndex,
                    title: col.title,
                    handleSave: this.handleSave,
                }),
            };
        });
        return (
            <div>
                <Table
                    components={components}
                    rowClassName={() => 'editable-row'}
                    bordered
                    dataSource={dataSource}
                    columns={columns}
                />
            </div>
        );
    }
}

export default EditableTable;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值