react-draft-wysiwyg github作者
组件demo
admin.jsx 后台管理的路由组件
原来设置height: ‘100%’, 由于富文本组件太大,会覆盖footer组件。所以改为最小高度minHeight
<Layout style={{ minHeight: '100%' }}>
1.初始化商品描述需要将html格式字符串转为富文本格式。文档的最下面
2.编辑器显示图片。文档最下面
得到图片怎么展示到编辑器
uploadImageCallBack函数,两个功能(上传图片,在编辑器展示图片)
xhr.open("POST", "/manage/img/upload"); // 请求地址
const data = new FormData();
data.append("image", file); //请求参数名
xhr.send(data);
xhr.addEventListener("load", () => {
const response = JSON.parse(xhr.responseText); // 后台响应数据
let url = response.data.url; //图片地址
resolve({ data: { link: url } });
});
<Item
label="商品详情"
labelCol={{ span: 2 }}
wrapperCol={{ span: 20 }}
>
<RichTextEditor ref={this.editor} detail={product.detail} />
</Item>
1.接口请求函数
2.收集数据
3.根据结果提示信息
onFinish = async (values) => {
const imgs = this.pw.current.getImgs()
const detail = this.editor.current.getDetail()
const { name, desc, price, categoryIds } = values
let pCategoryId = '', categoryId = ''
if (categoryIds.length === 1) {
pCategoryId = '0'
categoryId = categoryIds[0]
} else {
pCategoryId = categoryIds[0]
categoryId = categoryIds[1]
}
const product = { name, desc, price, pCategoryId, categoryId, detail, imgs }
if (this.isUpdate) {
product._id = this.product._id
}
// 发生请求
const result = await reqAddOrUpdateProduct(product)
if (result.status === 0) {
message.success(`${this.isUpdate ? '更新' : '添加'}商品成功`)
this.props.history.goBack()
} else {
message.error(`${this.isUpdate ? '更新' : '添加'}商品失败`)
}
}
用户归属于一种角色,每种角色能看到的菜单栏不一样。也可以说角色用来限制用户的功能。
期望的静态页面
控制变量,this.state。role实际指向roles中的某个元素,所以修改role对象的属性值,roles的该元素也会变。
state = {
roles: [], // 所有角色的列表
role: {}, // 选中的 role
}
数组的原因是,有可能是多选框。数组的元素就 决定 哪些行被选中。
期望不是点击按钮才处于选中状态,而不是点击该行容易地方都选择按钮。
通过点击事件,拿到被选中的行数据,更新this.state.role。设置selectedRowKeys数组,Table展现哪行被选中。
知识点一:
注意空对象也是true
a = {}
if(a) //true
知识点二:
地址(引用)没变,react建议不要直接修改数据
const roles = this.state.roles // 不建议
roles.push(role)
this.setState({roles})
知识点三:
render: (create_time) => formateDate(create_time)
可以简写成
render: formateDate
antd 4.x 比 3.x简洁 很多回调函数需要自己去测试,在知道具体的参数代表什么。
onCheck = (checkedKeys) => {
console.log("onCheck", checkedKeys);
}
只是在第一次构建AuthForm组件时,state记录了这次传过来的menus。如果后续再点击时,新的role就没有更新state状态数据了。
constructor(props) {
super(props)
// 根据传入角色的 menus 生成初始状态
const { menus } = this.props.role
this.state = {
checkedKeys: menus,
};
this.treeData = menuConfig
}
之前为了解决情况表单,我们使用了Modal组件的destroyOnClose={true}
属性,删除了子元素。
方法二:
利用生命周期钩子,该方法第一次渲染组件不会调用。当父组件render导致子组件第二次渲染时,就会调用。nextProps接收新的props数据。
因为属于生命周期的流程,所以可以任性地直接修改state状态数据。
selectedRowKeys: [role._id]
用一个数组(元素为每行的主键,key)来决定哪行代表选中状态。
而选中的这行数据,主要通过state状态
数据进行存储。
所以给我们一个假象是:点击选中这行就能直接传数据给子组件
onRow = (record) => {
return {
onClick: event => {
this.setState({ role: record })
},
}
}
selected = (record, selected) => {
// console.log(selected)
if (selected) {
this.setState({ role: record })
} else { // 复选框才能打击取消选择
this.setState({ role: {} })
}
}
render() {
const { roles, role, isShowAdd, isShowAuth } = this.state
return (
<Card title={title}>
<Table bordered
rowKey='_id'
dataSource={roles}
columns={this.columns}
pagination={{ defaultPageSize: PAGE_SIZE }}
rowSelection={{
type: 'radio',
selectedRowKeys: [role._id],
onSelect: this.selected
}}
onRow={this.onRow}
/>
<Modal title="添加角色" visible={isShowAdd}
onCancel={() => {
this.setState({ isShowAdd: false })
}}
onOk={this.addRole}
destroyOnClose={true}
>
<AddForm
setForm={form => this.form = form}
/>
</Modal>
<Modal title="设置角色权限" visible={isShowAuth}
onOk={this.updateRole}
onCancel={() => {
this.setState({ isShowAuth: false })
// this.form.current.resetFields()
}}
destroyOnClose={true}
>
<AuthForm ref={this.auth} role={role} />
</Modal>
</Card>
)
}
checkedKeys={checkedKeys}
这里也是靠一个数组(元素为每个节点的key)来决定哪些节点处于选中状态。
注意,如果父节点的所有子节点被选中,父节点的key也会存在checkedKeys,但只要一个子节点未选中,就不包含父节点的key
export default class AuthForm extends Component {
static propTypes = {
role: PropTypes.object.isRequired,
};
constructor(props) {
super(props)
// 根据传入角色的 menus 生成初始状态
const { menus } = this.props.role
this.state = {
checkedKeys: menus,
};
//菜单栏数组,元素为对象,包含title,key,children即可代表树形结构
this.treeData = menuConfig
}
// 为父组件提供最新 menus 数据的方法
getMenus = () => this.state.checkedKeys
// 点击复选框触发
onCheck = (checkedKeys) => {
console.log("onCheck", checkedKeys);
this.setState({ checkedKeys })
}
render() {
const { role } = this.props
const { checkedKeys } = this.state
const formItemLayout = {
labelCol: { span: 4 }, //左侧label宽度
wrapperCol: { span: 15 }, //右侧包裹输入框宽度
};
return (
<div>
<Item {...formItemLayout} label='角色名称'>
<Input value={role.name} disabled />
</Item>
<Tree
checkable
defaultExpandAll={true}
checkedKeys={checkedKeys}
onCheck={this.onCheck}
treeData={this.treeData}
/>
</div>
)
}
}