富文本编辑器组件
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>
add-update.jsx 提交表单事件
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 ? '更新' : '添加'}商品失败`)
}
}
角色管理
用户归属于一种角色,每种角色能看到的菜单栏不一样。也可以说角色用来限制用户的功能。
roles数据库
Table表格
期望的静态页面 控制变量,this.state。role实际指向roles中的某个元素,所以修改role对象的属性值,roles的该元素也会变。
state = {
roles: [],
role: {},
}
第一列是联动的选择框。可以通过 rowSelection.type 属性指定选择类型,默认为 checkbox。
数组的原因是,有可能是多选框。数组的元素就 决定 哪些行被选中。
期望不是点击按钮才处于选中状态,而不是点击该行容易地方都选择按钮。
onRow: 设置行属性 onRow的值为函数,函数返回一个对象,对象的属性为不同的事件处理函数。
通过点击事件,拿到被选中的行数据,更新this.state.role。设置selectedRowKeys数组,Table展现哪行被选中。
知识点一: 注意空对象也是true
a = {}
if(a)
知识点二: 地址(引用)没变,react建议不要直接修改数据
const roles = this.state.roles
roles.push(role)
this.setState({roles})
知识点三: render: (create_time) => formateDate(create_time) 可以简写成 render: formateDate
Tree树形控件
antd 4.x 比 3.x简洁 很多回调函数需要自己去测试,在知道具体的参数代表什么。
onCheck = (checkedKeys) => {
console.log("onCheck", checkedKeys);
}
只是在第一次构建AuthForm组件时,state记录了这次传过来的menus。如果后续再点击时,新的role就没有更新state状态数据了。
constructor(props) {
super(props)
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) => {
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 })
}}
destroyOnClose={true}
>
<AuthForm ref={this.auth} role={role} />
</Modal>
</Card>
)
}
Tree树形控件 antd4.x版
checkedKeys={checkedKeys} 这里也是靠一个数组(元素为每个节点的key)来决定哪些节点处于选中状态。
注意,如果父节点的所有子节点被选中,父节点的key也会存在checkedKeys,但只要一个子节点未选中,就不包含父节点的key
export default class AuthForm extends Component {
static propTypes = {
role: PropTypes.object.isRequired,
};
constructor(props) {
super(props)
const { menus } = this.props.role
this.state = {
checkedKeys: menus,
};
this.treeData = menuConfig
}
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 },
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>
)
}
}
想着用新生命周期钩子代替,但不行,因为 而树形控件,有时需要传过来的props决定,有时有state决定。
|