详细剖析|袋鼠云数栈前端框架Antd 3.x 升级 4.x 的踩坑之路
袋鼠云数栈从2016年发布第⼀个版本开始,就始终坚持着以技术为核⼼、安全为底线、提效为⽬标、中台为战略的思想,坚定不移地⾛国产化信创路线,不断推进产品功能迭代、技术创新、服务细化和性能升级。
在数栈过去的产品迭代中受限于当前组件的版本,积累了很多待解决的问题,随着新的功能需求不断增加,很多原先的组件以及交互设计需要进行优化。
2月,伴随着数栈 UI5.0 的焕新升级,数栈前端团队一起将组件框架 antd 从 v3.x 升级到了 v4.x,更新组件的 UI,提升产品的交互体验,使数栈产品能够更加灵活地适应未来产品功能迭代的需求。
本文将总结归纳袋鼠云数栈前端框架Antd 从3.x 升级到4.x 的相关步骤,及在这个过程中踩过的坑,解决的问题。
兼容性问题
第三方依赖兼容问题
· React - 最低 v16.9,部分组件使用 hooks 重构 ( react 升级相关文档:https://sourl.cn/6bM4Ep)
· Less - 最低 v3.1.0,建议升级到 less 4.x;
· @ant-design/icons-antd - 不再内置 Icon 组件,请使用独立的包。
对 3.x 的兼容性处理
或许是考虑到部分组件升级的毁坏性,antd4.x 中依然保留了对 3.x 版本的兼容,废弃的组件通过 @ant-design/compatible 保持兼容,例如 Icon、Form。
注意:建议 @ant-design/compatible 仅在升级过程中稍作依赖,升级 4.x 请完全剔除对该过渡包的依赖。
升级步骤
只有一步
@ant-design/codemod-v4 自带升级脚本,会自动替换代码。
# 通过 npx 直接运行
npx -p @ant-design/codemod-v4 antd4-codemod apps/xxxx# 或者全局安装
# 使用 npm
npm i -g @ant-design/codemod-v4
# 或者使用 yarn
yarn global add @ant-design/codemod-v4# 运行
antd4-codemod src
注意:该命令和脚本只会进行代码替换,不会进行 AntD 的版本升级,需要手动将其升级至4.22.5。
该命令完成的工作:1. 将 Form 与 Mention 组件通过 @ant-design/compatible 包引入 2. 用新的 @ant-design/icons 替换字符串类型的 icon 属性值 3. 将 Icon 组件 + type =“” 通过 @ant-design/icons 引入 4. 将 v3 LocaleProvider 组件转换成 v4 ConfigProvider 组件 5. 将 Modal.method() 中字符串 icon 属性的调用转换成从 @ant-design/icons 中引入
antd4-codemod
上图这类报错是 Icon 组件自动替换错误,有 2 种处理方式:
· 报错文件的 Icon 比较少的情况,可以直接手动替换该文件中的 Icon 组件,具体替换成 Icon 中的哪个组件可以根据 type 在 Icon 文档中找( Icon文档:https://sourl.cn/neHBVS );
· 下图中是具体报错的节点,可以看到 JSXSpreadAttribute 节点也就是拓展运算符中没有 name 属性,所以把 Icon 组件的拓展运算符改一下再执行替换脚本就可以了。
antd4 问题修复
styled-components
styled-components 依赖需要转换写法。
Icon
不要使用兼容包的 icon。 在 3.x 版本中,Icon 会全量引入所有 svg 图标文件,增加了打包产物; 在 4.x 版本中,对 Icon 进行了按需加载,将每个 svg 封装成一个组件。
注意:antd 不再内置 Icon 组件,请使用独立的包 @ant-design/icons。
· 使用
import { Icon } from 'antd';
mport { SmileOutlined } from '@ant-design/icons';const Demo = () => (<div><Icon type="smile" /><SmileOutlined /><Button icon={<SmileOutlined />} /></div>
);
· 兼容
import { Icon } from '@ant-design/compatible';
const Demo = () => (<div><Icon type="smile" /><Button icon="smile" /></div>
);
Form
antd Form 从 v3 到 v4:https://sourl.cn/7TiRfp
● Form.create()
在 3.x 中,表单中任意一项的修改,都会导致 Form.create() 包裹的表单重新渲染,造成性能消耗; 在 4.x 中,Form.create() 不再使用。 如果需要使用 form 的 api,例如 setFieldsValue 等,需要通过 Form.useForm() 创建 Form 实体进行操作。
· 函数组件写法
// antd v4
const Demo = () => {const [form] = Form.useForm();React.useEffect(() => {form.setFieldsValue({username: 'Bamboo',});}, []);return (<Form form={form} {...props}> ... </Form>)
};
· 如果是 class component,也可以通过 ref 获取
class Demo extends React.Component {formRef = React.createRef();componentDidMount() {this.formRef.current.setFieldsValue({username: 'Bamboo',});}render() {return (<Form ref={this.formRef}><Form.Item name="username" rules={[{ required: true }]}><Input /></Form.Item></Form>);}
}
当我们使用 From.create() 的时候,可能会传入参数,做数据处理,例如:
export const FilterForm: any = Form.create<Props>({onValuesChange: (props, changedValues, allValues) => {const { onChange } = props;onChange(allValues);},
})(Filter);
由于 Form.create 的删除,需要放到 < Form> 中。
<Formref={this.formRef}layout="vertical"className="meta_form"onValuesChange={(_, allValues) => {const { onChange } = this.props;onChange(allValues);}}
>
● getFieldDecorator
在 4.x 中,不在需要 getFieldDecorator 对 Item 进行包裹。注意以下问题:
· 将之前写在 getFieldDecorator 中的 name/rules 等移到属性中;
· 初始化在 form 中处理,避免同名字段冲突问题;
· 关于表单联动的问题,官方提供了 shouldUpdate 方法。
const Demo = () => (<Form initialValues={{ username: 'yuwan' }}><Form.Item name="username" rules={[{ required: true }]}><Input /></Form.Item></Form>
);
● initialValue
· 历史问题
initialValue 从字面意来看,就是初始值 defaultValue,但是可能会有部分同学使用他的时候会误以为 initialValue 等同于 value。造成这样的误解是因为在 3.x 的版本中,一直存在一个很神奇的问题,受控组件的值会跟随 initialValue 改变。
看下面的例子,点击 button 修改 username, input 框的 value 也会随之改变。
const Demo = ({ form: { getFieldDecorator } }) => (const [username, setUsername] = useState('');const handleValueChange = () => {setUsername('yuwan');}return (<Fragment><Form><Form.Item>{getFieldDecorator('username', {initialValue: username,rules: [{ required: true }],})(<Input />)}</Form.Item></Form><Button onClick={handleValueChange}>Change</Button></Fragment>)
);const WrappedDemo = Form.create()(Demo);
但当 input 框被编辑过,initialValue 和 input 的绑定效果就消失了,正确的做法应该是通过 setFieldsVlaue 方法去 set 值。
· 4.x 版本的 initialValue
在 4.x,antd 团队已经把这个 bug 给解了,并且一是为了 name 重名问题,二是再次强调其初始值的功能,现在提到 Form 中了。当然,如果继续写在 Form. Item 中也是可以的,但需要注意优先级。
● shouldUpdate
前面有说过,form 表单不再会因为表单内部某个值的改变而重新渲染整个结构,而设有 shouldUpdate 为 true 的 Item,任意变化都会使该 Form. Item 重新渲染。
它会接收 render props,从而允许你对此进行控制。这里稍微注意一下,请勿在设置 shouldUpdate 的外层 Form. Item 上添加 name, 否则,你会得到一个 error。
<Form.Item shouldUpdate={(prev, next) => prev.name !== next.name}>{form => form.getFieldValue('name') === 'antd' && (<Form.Item name="version"><Input /></Form.Item>)}
</Form.Item>
在使用 shouldUpdate 的时候,需要在第一个 Form.Item 上加上 noStyle,否则就会出现下面这种留白占位的情况。
● validateTrigger
onBlur 时不再修改选中值,且返回 React 原生的 event 对象。如果你在使用兼容包的 Form 且配置了 validateTrigger 为 onBlur ,请改至 onChange 以做兼容。
● validator
在 antd3 时,我们使用 callback 返回报错。但是 antd4 对此做了修改,自定义校验,接收 Promise 作为返回值。示例参考如下:
· antd3 的写法
<FormItem label="具体时间" {...formItemLayout}>{getFieldDecorator('specificTime', {rules: [{required: true,validator: (_, value, callback) => {if (!value || !value.hour || !value.min) {return callback('具体时间不可为空');}callback();},},],})(<SpecificTime />)}
</FormItem>
· antd4 的写法
<FormItemlabel="具体时间"{...formItemLayout}name="specificTime"rules={[{required: true,validator: (_, value) => {if (!value || !value.hour || !value.min) {return Promise.reject('具体时间不可为空');}return Promise.resolve();},},]}
><SpecificTime />)
</FormItem>
● validateFields
不再支持 callback,该方法会直接返回一个 Promise,可以通过 then / catch 处理。
this.formRef.validateFields().then((values) => {onOk({ ...values, id: appInfo.id || '' });
}).catch(({ errorFields }) {this.formRef.scrollToField(errorFields[0].name);})
或者使用 async/await。
try {const values = await validateFields();
} catch ({ errorFields }) {scrollToField(errorFields[0].name);
}
● validateFieldsAndScroll
该 api 被拆分了,将其拆分为更为独立的 scrollToField 方法。
onFinishFailed = ({ errorFields }) => {form.scrollToField(errorFields[0].name);
};
● form.name
在 antd 3.x 版本,绑定字段时,可以采用 . 分割的方式。如:
getFieldDecorator('sideTableParam.primaryKey')
getFieldDecorator('sideTableParam.primaryValue')
getFieldDecorator('sideTableParam.primaryName')
在最终获取 values 时,antd 3.x 的版本会对字段进行汇总,得到如下:
const values = {sideTableParam: {primaryKey: xxx,primaryValue: xxx,primaryName: xxx,}
}
而在 antd 4.x下,会得到如下的 values 结果:
const values = {'sideTableParam.primaryKey': xxx,'sideTableParam.primaryValue': xxx,'sideTableParam.primaryName': xxx,
}
· 解决方法
在 antd 4.x 版本传入数组。
name={['sideTableParam', 'primaryKey']}
name={['sideTableParam', 'primaryValue']}
name={['sideTableParam', 'primaryName']}
使用 setFieldsValue 设置值:
setFieldsValue({sideTableParam: [{primaryKey: 'xxx',primaryValue: 'xxx',primaryName: 'xxx',},],
});
当我们使用 name={['sideTableParam', 'primaryKey']} 方式绑定值的时候,与其关联的 dependencies/getFieldValue 都需要设置为['sideTableParam', 'primaryKey'],例如:
<FormItem dependencies={[['alert', 'sendTypeList']]} noStyle>{({ getFieldValue }) => {const isShowWebHook = getFieldValue(['alert', 'sendTypeList'])?.includes(ALARM_TYPE.DING);return (isShowWebHook &&RenderFormItem({item: {label: 'WebHook',key: ['alert', 'dingWebhook'],component: <Input placeholder="请输入WebHook地址" />,rules: [{required: true,message: 'WebHook地址为必填项',},],initialValue: taskInfo?.alert?.dingWebhook || '',},}));}}
</FormItem>
当我们希望通过 validateFields 拿到的数据是数组时,例如这样:
我们可以设置为这样:
const formItems = keys.map((k: React.Key) => (<Form.Item key={k} required label="名称"><Form.ItemnoStylename={['names', k]}rules={[{ required: true, message: '请输入标签名称' },{ validator: utils.validateInputText(2, 20) },]}><Input placeholder="请输入标签名称" style={{ width: '90%', marginRight: 8 }} /></Form.Item><i className="iconfont iconicon_deletecata" onClick={() => this.removeNewTag(k)} /></Form.Item>
));
● Tooltip
Form 支持属性 tooltip,能够在 label 后产生一个问号直接做提示。
● extra
针对于想放置于组件下面内容可以使用 extra 来实现。
<FormItemlabel="过滤条件"extra={<Tooltip title={customSystemParams}>系统参数配置 <QuestionCircleOutlined /></Tooltip>}
><Input.TextArea />
</FormItem>
● Form 在数栈的变化
通过这次 UI 升级和 antd 升级之后,Form 表单在数栈中的应用发生了较大的变化,从老版本的 label/component 横向排版改为了纵向改版,在横向空间不⾜的情况下,使⽤上下结构能有效提⾼填写表单的效率。
Select
● rc-select
· 底层重写
• 解决些许历史问题
1)rc-select & rc-select-tree 的 inputValue & searchValue 之争。rc-select-tree 是 rc-select 结合 tree 写的一个组件,相似但又不同,searchValue 就是其中一点,也不是没人提过 issue,只是人的忘性很大,时间长了就忘了、混淆了,导致在 rc-select 中甚至出现了 searchValue 的字样。
2)inputValue 历史问题,this.state.inputValue。
3)onSelect 清空了值,又会被 onChange 赋值回来。
• 模块复用
在新版的 rc-select 中,antd 官方抽取了一个 generator 方法。它主要接收一个 OptionList 的自定义组件用于渲染下拉框部分。这样我们就可以直接复用选择框部分的代码,而自定义 Select 和 TreeSelect 对应的列表或者树形结构了。
● labelInValue
在 3.x 版本为 {key: string, label: ReactNode}
在 4.x 版本为 {value: string, label: ReactNode}
Table
● fixed
固定列时,文字过长导致错位的问题,被完美解决了。
· 历史原因
3.x 中对 table fixed 的实现,是写了两个 table, 顶层 fixed 的是一个,底层滚动的是一个,这样出现这种错位的问题就很好理解了。
要解决也不是没有办法,可以在特定的节点去测算表格列的高度,但是这个行为会导致重排,影响性能问题。
· 解决方案
4.x 中,table fixed 不在通过两个 table 来实现,他使用了一个 position 的新特性:position: sticky;
元素根据正常文档流进行定位,然后相对它的最近滚动祖先(nearest scrolling ancestor)和 containing block (最近块级祖先 nearest block-level ancestor),包括 table-related 元素,基于 top、right、bottom 和 left 的值进行偏移,偏移值不会影响任何其他元素的位置。
优点:
• 根据正常文档流进行定位
• 相对最近滚动祖先 & 最近块级祖先进行偏移
缺点:
• 不兼容 <= IE11
解决了使用 absolute | fixed 脱离文档流无法撑开高度的问题,也不再需要对高度进行测量。
● table.checkbox
· 问题描述
升级后,checkbox 宽度被挤压了。
· 解决方案
通过在 rowSelection 中设置 columnWidth 和 fixed 解决。
const rowSelection = {fixed: true,columnWidth: 45,selectedRowKeys,onChange: this.onSelectChange,
};
● 渲染条件
antd4 Table 对渲染条件进行了优化,对 props 进行“浅比较”,如果没有变化不会触发 render。
● 类名更改
.ant-table-content 更改为 .ant-table-container
.ant-form-explain 更改为 .ant-form-item-explain
● dataIndex 修改
在 antd3.0 的时候,我们采用 user.userName 能够读到嵌套的属性。
{title: '账号',dataIndex: 'user.userName',key: 'userName',width: 200,
}
antd4.0 对此做了修改,同 Form 的 name。
{title: '账号',dataIndex: ['user', 'userName'],key: 'userName',width: 200,
}
● table pagination showSizeChanger
· 问题描述
升级 antd4 后,发现一些表格分页器多了 pageSize 切换的功能,代码中 onChange 又未对 size 做处理,会导致底部分页器 pageSize 和数据对不上,因此需要各自排查 Table 的 pagination 和 Pagination 组件,和请求列表接口的参数。
<TablerowKey="userId"pagination={{total: users.totalCount,defaultPageSize: 10,}}onChange={this.handleTableChange}style={{ height: tableScrollHeight }}loading={this.state.loading}columns={this.initColumns()}dataSource={users.data}scroll={{ x: 1100, y: tableScrollHeight }}
/>handleTableChange = (pagination: any) => {this.setState({current: pagination.current,},this.search);
};
search = (projectId?: any) => {const { name, current } = this.state;const { project } = this.props;const params: any = {projectId: projectId || project.id,pageSize: 10,currentPage: current || 1,name: name || undefined,removeAdmin: true,};this.loadUsers(params);
};
antd4.0 对此做了修改,同 Form 的 name。
<TablerowKey="userId"pagination={{showTotal: (total) => `共${total}条`,total: users.totalCount,current,pageSize,}}onChange={this.handleTableChange}style={{ height: tableScrollHeight }}loading={this.state.loading}columns={this.initColumns()}dataSource={users.data}scroll={{ x: 1100, y: tableScrollHeight }}
/>handleTableChange = (pagination: any) => {this.setState({current: pagination.current,pageSize: pagination.pageSize,},this.search);
};search = (projectId?: any) => {const { name, current, pageSize } = this.state;const { project } = this.props;const params: any = {projectId: projectId || project.id,pageSize,currentPage: current || 1,name: name || undefined,removeAdmin: true,};this.loadUsers(params);
};
另外,一些同学在 Table 中既写了 onChange,也写了 onShowSizeChange,这个时候要注意,当切换页码条数的时候两个方法都会触发,onShowSizeChange 先触发,onChange 后触发,这个时候如果 onChange 内未对 pageSize 做处理可能导致切页失败,看下面代码就明白了,写的时候稍微注意一下即可。
● table sorter columnKey
· 问题描述
表格中如果要对表格某一字段进行排序需要在 columns item 里设置 sorter 字段,然后在 onChange 里拿到 sorter 对象进行参数处理,再请求数据。
需要注意的是,很多用到了 sorter.columnKey 来进行判断,容易出现问题,sorter.columnKey === columns item.key,如果未设置 key,那么获取到的 columnKey 就为空,导致搜索失效,要么设置 key,再进行获取。同理, sorter.field === columns item.dataIndex,设置 dataIndex,通过 sorter.field 进行获取,两者都可以。
columns={[{title: '创建时间',dataIndex: 'gmtCreate1',key: 'aa',sorter: true,render(n: any, record: any) {return DateTime.formatDateTime(record.gmtCreate);}},...]
}
onChange={(pagination: any, filters: any, sorter: any) {console.log(pagination, '--pagination');console.log(filters, '--filters');console.log(sorter, '--sorter');
}}
● Table 在数栈的变化
通过这次 UI 升级和 antd 升级之后,表格在数栈中的应用发生了较大的变化,减⼩了表格默认⾼度,增加⼀屏可浏览的数据数量。
Tree
Tree 组件取消 value 属性,现在只需要添加 key 属性即可。
特别注意, 此问题会导致功能出问题,需要重点关注!!!
在项目中经常在 TreeItem 中增加参数,如:< TreeItem value={value} data={data} >。在拖拽等回调中就可以通过 nodeData.props.data 的方式获取到 data 的值。但在 antd4 中,获取参数的数据结构发生了改变,原先直接通过 props 点出来的不行了。
· 有两种方式取值:
1)不使用props。直接采用 nodeData.data 的方式,也可以直接拿到。
2)继续使用 props。在antd4中,还是可以通过 props 找到参数,只不过 antd 会把所有参数使用 data 进行包裹,就需要改成 nodeData.props.data.data。
· 新版数据结构如下:
· drag
拖拽节点位置的确定与 3.x 相比进行了变更,官网并没有说明。具体如下图:
左侧为 3.x,右侧为 4.x。 在3.x版本,只要把节点拖拽成目标节点的上中下,即代表着目标节点的同级上方,子集,同级下方;
在 4.x 版本,是根据当前拖拽节点与目标节点的相对位置进行确定最终的拖拽结果。
当拖拽节点处于目标节点的下方,且相对左侧对齐的位置趋近于零,则最终的位置为目标节点的同级下方。
当拖拽节点处于目标节点的下方,且相对左侧一个缩近的位置,则最终的位置为目标节点的子集。
当拖拽节点处于目标节点的上方,且相对左侧对齐的位置趋近于零,则最终的位置为目标节点的同级上方。
Pagination
Pagination自 4.1.0 版本起,会默认将 showSizeChanger 参数设置为 true ,因而在数据条数超过50时,pageSize 切换器会默认显示。这个变化同样适用于 Table 组件,可通过 showSizeChanger: false 关闭。
如果 size 属性值为 small,则删除 size 属性。
Drawer
当我们在 Drawer 上 设置了 getContainer={false} 属性之后,Drawer 会添加上 .ant-drawer-inline 的类名导致我们 position: fixed 失效。
Button
在 antd 3.0 中危险按钮采用 type。
使用如下:涉及改动点 type、dangr 属性。
Tabs
使标签页不被选中。
// 3.x
activeKey={undefined}
// 4.x
activeKey={null}
总结
该篇文章详细讲解了数栈前端团队如何从 antd3 升级到 antd4 的详细步骤,以及团队在实践过程中发现的一些问题和对应的解决方案,为后续产品的开发体验打了基础,也提供了一种更好的交互体验。
未来数栈前端团队将会持续关注产品体验以及开发中的技术痛点,以开发更好的产品为导向,助力业务发展。 《数据治理行业实践白皮书》下载地址:https://fs80.cn/380a4b
想了解或咨询更多有关袋鼠云大数据产品、行业解决方案、客户案例的朋友,浏览袋鼠云官网:https://www.dtstack.com/?src=szcsdn
同时,欢迎对大数据开源项目有兴趣的同学加入我们,一起交流最新开源技术信息,号码:30537511,项目地址:https://github.com/DTStack
相关文章:
详细剖析|袋鼠云数栈前端框架Antd 3.x 升级 4.x 的踩坑之路
袋鼠云数栈从2016年发布第⼀个版本开始,就始终坚持着以技术为核⼼、安全为底线、提效为⽬标、中台为战略的思想,坚定不移地⾛国产化信创路线,不断推进产品功能迭代、技术创新、服务细化和性能升级。 在数栈过去的产品迭代中受限于当前组件的…...
【C++PrimerPlus】第三章 处理数据
文章目录前言内容目录3.1 简单变量3.1.2 变量名3.1.2 整形3.1.3 整形short,int,long,long long3.1.4 无符号类型3.1.5 选择整形类型3.1.6 整形字面值3.1.7 C如何确定常量的类型3.1.8 char类型:字符和小整数3.1.9 bool类型3.2 const修饰符3.3浮点数3.3.1 书写浮点数3…...
【基础算法】单链表的OJ练习(1) # 反转链表 # 合并两个有序链表 #
文章目录前言反转链表合并两个有序链表写在最后前言 上一章讲解了单链表 -> 传送门 <- ,后面几章就对单链表进行一些简单的题目练习,目的是为了更好的理解单链表的实现以及加深对某些函数接口的熟练度。 本章带来了两个题目。一是反转链表&#x…...
离散数学笔记(1)命题逻辑
文章目录1.命题符号化及联结词基本概念本节题型2.命题公式及分类基本概念本节题型1.命题符号化及联结词 基本概念 命题的定义:能够判断真假的陈述句称为命题。 备注:感叹句、疑问句、祈使句和类似于xy>5之类真值不唯一的句子都不是命题。 真值的真假…...
IDEA Android 网格布局(GridLayout)示例(计算器界面布局)
网格布局(GridLayout) 示例程序效果(实现类似vivo手机自带计算器UI) 真机和模拟器运行效果: 简述: GridLayout(网格布局)和TableLayout(表格布局)有类似的地方,通俗来讲可以理解为…...
【蓝桥杯嵌入式】拓展板之数码管显示
文章目录硬件电路连接方式函数实现文章福利硬件电路 通过上述原理图,可知拓展板上的数码管是一个共阴数码管,也就是说某段数码管接上高电平时,就会点亮。 上述原理图还给出一个提示,即:三个数码管分别与三个74HC59…...
Web Spider案例 网洛克 第三题 AAEncode加密 练习(七)
声明 此次案例只为学习交流使用,抓包内容、敏感网址、数据接口均已做脱敏处理,切勿用于其他非法用途; 文章目录声明一、资源推荐二、逆向目标三、抓包分析 & 下断分析逆向3.1 抓包分析3.2 下断分析逆向拿到混淆JS代码3.3 AAEncode解决方…...
【javaScript面试题】2023前端最新版javaScript模块,高频24问
🥳博 主:初映CY的前说(前端领域) 🌞个人信条:想要变成得到,中间还有做到! 🤘本文核心:博主收集的关于javaScript的面试题 目录 一、2023javaScript面试题精选 1.js的数据类型…...
Hadoop集群启动从节点没有DataNode
一、问题背景 之前启动hadoop集群的时候都没有问题,今天启动hadoop集群的时候,从节点的DataNode没有启动起来。 二、解决思路 遇见节点起不来的情况,可以去看看当前节点的日志文件 我进入当前从节点的hadoop安装目录的Logs文件下去查看日…...
FIFO IP Core
FIFO IP Core 先进先出的缓存器常常被用于数据的缓存,或者高速异步数据交互(跨时钟信号传递)和RAM和ROM的区别是没有地址线,无法指定地址 写时钟(Write Clock Domain),读时钟写复位(wr_rst),读…...
从FPGA说起的深度学习(四)
这是新的系列教程,在本教程中,我们将介绍使用 FPGA 实现深度学习的技术,深度学习是近年来人工智能领域的热门话题。在本教程中,旨在加深对深度学习和 FPGA 的理解。用 C/C 编写深度学习推理代码高级综合 (HLS) 将 C/C 代码转换为硬…...
pytorch入门7--自动求导和神经网络
深度学习网上自学学了10多天了,看了很多大神的课总是很快被劝退。终于,遇到了一位对小白友好的刘二大人,先附上链接,需要者自取:https://b23.tv/RHlDxbc。 下面是课程笔记。 一、自动求导 举例说明自动求导。 torch中的…...
QT 之wayland 事件处理分析基于qt5wayland5.14.2
1. Qt wayland 初始化 接收鼠标/案件,触摸屏等事件事件 QWaylandNativeInterface : public QPlatformNativeInterface 在QWaylandNativeInterface 继承qpa 接口类QPlatformNativeInterface; 1.1 初始化鼠标: void *QWaylandNativeInterface::nativeR…...
【this 和 super 的区别】
在 Java 中,this 和 super 都是关键字,表示当前对象和父类对象。 this 关键字可以用于以下几种情况: 引用当前对象的成员变量,方法和构造方法,用于区分局部变量和成员变量重名的情况; 调用当前类的另外一…...
K8s:Monokle Desktop 一个集Yaml资源编写、项目管理、集群管理的 K8s IDE
写在前面 Monokle Desktop 是 kubeshop 推出的一个开源的 K8s IDE相关项目还有 Monokle CLI 和 Monokle Cloud相比其他的工具,Monokle Desktop 功能较全面,涉及 k8s 管理的整个生命周期博文内容:Monokle Desktop 下载安装,项目管理…...
自动化测试实战篇(8),jmeter并发测试登录接口,模拟从100到1000个用户同时登录测试服务器压力
首先进行使用jmeter进行并发测试之前就需要搞清楚线程和进程的区别还需要理解什么是并发、高并发、并行。还需要理解高并发中的以及老生常谈的,TCP三次握手协议和TCP四次握手协议**TCP三次握手协议指:****TCP四次挥手协议:**进入Jmeter&#…...
ATTCK v12版本战术实战研究—持久化(二)
一、前言前几期文章中,我们介绍了ATT&CK中侦察、资源开发、初始访问、执行战术、持久化战术的知识。那么从前文中介绍的相关持久化子技术来开展测试,进行更深一步的分析。本文主要内容是介绍攻击者在运用持久化子技术时,在相关的资产服务…...
python函数式编程
1 callable内建函数判断一个名字是否为一个可调用函数 >>> import math >>> x 1 >>> y math.sqrt >>> callable(x) False >>> callable(y) True 2 记录函数(文档字符串) >>> def square(x): …...
3.linux下安装mysql
1.安装前的环境准备 查看是否安装过mysql 首先检测Linux操作系统中是否安装了MySQL: # rpm -qa | grep -i mysql 卸载安装包 如果有信息出现,则进行删除,命令如下: # rpm -e --nodeps 包名 删除老版本mysql的开发头文件和…...
17、MySQL分库分表,原理实战
MySQL分库分表,原理实战 1.MyCAT分布式架构入门及双主架构1.1 主从架构1.2 MyCAT安装1.3 启动和连接1.4 配置文件介绍2.MyCAT读写分离架构2.1 架构说明2.2 创建用户2.3 schema.xml2.4 连接说明2.5 读写测试2.6 当前是单节点3.MyCAT高可用读写分离架构3.1 架构说明3.3 schema.xm…...
【C++的OpenCV】第九课-OpenCV图像常用操作(六):图像形态学-阈值的概念、功能及操作(threshold()函数))
目录一、阈值(thresh)的概念二、阈值在图形学中的用途三、阈值的作用和操作3.1 在OpenCV中可以进行的阈值操作3.2 操作实例3.2.1 threshold()函数介绍3.2.2 实例3.2.3 结果上节课的内容(作者还是鼓励各位同学按照顺序进行学习哦)&…...
[Java代码审计]—MCMS
环境搭建 MCMS 5.2.4:https://gitee.com/mingSoft/MCMS/tree/5.2.4/利用 idea 打开项目 创建数据库 mcms,导入 doc/mcms-5.2.8.sql 修改 src/main/resources/application-dev.yml 中关于数据库设置参数 启动项目登录后台 http://localhost:8080/ms/l…...
《程序员面试金典(第6版)》面试题 01.08. 零矩阵
题目描述 编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。 示例1: 输入:[1, 2, 3, 3, 2, 1] 输出:[1, 2, 3] -示例2: 输入:[1, 1, 1, 1, 2] 输出:[1, 2] 提示: 链表长度在[0, 20000]范…...
初识 Python
文章目录简介用途解释器命令行模式交互模式输入和输出简介 高级编程语言,解释型语言代码在执行时会逐行翻译成 CPU 能理解的机器码代码精简,但运行速度慢基础代码库丰富,还有大量第三方库代码不能加密 用途 网络应用工具软件包装其他语言开…...
常用sql语句分享
SELECT COUNT(DISTINCT money) FROM ac_association_course;#COUNT() 函数返回匹配指定条件的行数SELECT AVG(money) FROM ac_association_course;#AVG 函数返回数值列的平均值。NULL 值不包括在计算中SELECT id FROM ac_association_course order by id desc limit 1;#返回最大…...
极狐GitLab DevSecOps 为企业许可证安全合规保驾护航
本文来自: 小马哥 极狐(GitLab) 技术布道师 开源许可证是开源软件的法律武器,是第三方正确使用开源软件的安全合规依据。 根据 Linux 发布的 SBOM 报告显示,98% 的企业都在使用开源软件(中文版报告详情)。随着开源使用…...
后端程序员的前端基础-前端三剑客之HTML
文章目录1 HTML简介1.1 什么是HTML1.2 HTML能做什么1.3 HTML书写规范2 HTML基本标签2.1 结构标签2.2 排版标签2.3 块标签2.4 基本文字标签2.5 文本格式化标签2.6 标题标签2.7 列表标签(清单标签)2.8 图片标签2.9 链接标签2.10 表格标签3 HTML表单标签3.1 form元素常用属性3.2 i…...
VS2019加载解决方案时不能自动打开之前的文档(回忆消失)
✏️作者:枫霜剑客 📋系列专栏:C实战宝典 🌲上一篇: 错误error c3861 :“_T“:找不到标识符 逐梦编程,让中华屹立世界之巅。 简单的事情重复做,重复的事情用心做,用心的事情坚持做; 文章目录前言一、问题描…...
ConcurrentHashMap-Java八股面试(五)
系列文章目录 第一章 ArrayList-Java八股面试(一) 第二章 HashMap-Java八股面试(二) 第三章 单例模式-Java八股面试(三) 第四章 线程池和Volatile关键字-Java八股面试(四) 提示:动态每日更新算法题,想要学习的可以关注一下 文章目录系列文章目录一、…...
互联网衰退期,测试工程师35岁的路该怎么走...
国内的互联网行业发展较快,所以造成了技术研发类员工工作强度比较大,同时技术的快速更新又需要员工不断的学习新的技术。因此淘汰率也比较高,超过35岁的基层研发类员工,往往因为家庭原因、身体原因,比较难以跟得上工作…...
dede网站怎么做单页面/软件网站排行榜
点击上方“蓝色字”可关注我们!暴走时评:IT业巨头富士通日前推出一项新的咨询服务,并表示该服务将在短短五天内实现“随时可用”的区块链最低可行产品研发。该服务起价9900欧元,内容包括从区块链技术基础入门课程、拟议用例评估再…...
湘潭网站建设哪些公司/营销计划怎么写
Trick 【题目描述】 暴躁的稻草人,最终以自爆来给我们的队伍致命一击,全队血量见底,稻草人也一分为二。还好我们有雨柔妹子,瞬间精力回满。不过事后姜小弟和龙腹黑就开始了报复。 他们读取存档,将若干暴躁的稻草人活捉…...
做p2p网站的公司/seo建设招商
//这张表存放的是所有单据模板的信息表 如果不知道单据模板的信息后可在数据库中查询PUB_BILLTEMPLET//这张表是打印模板的表改模板可以再此表修改pub_print_template//获取表头某个字段的值getBillCardPanel().getHeadItem("kitarea").getValueObject()//获取当前登…...
怎么查看网站有没有做ssl/2345系统导航
% and_hand.m 手算实现与逻辑%% 清理close allclear,clc%% 定义变量P[0,0,1,1;0,1,0,1] % 输入向量P[ones(1,4);P] % 包含偏置的输入向量d[0,0,0,1] % 期望输出向量% 初始化w…...
wordpress广告管理插件/seo和sem的区别
Android 学习已有一年半有余,先后做过两款游戏、三款应用和搭建一台服务端,也了解过一些Android相关的源码(JDK、SDK和NDK) 后来想学深入点,搞过两款开源项目(LGame和AChartEngine),…...
免费做网站的/网络营销管理
Simulink 是面向框图的仿真软件。7.1 演示一个Simulink 的简单程序【例7.1】创建一个正弦信号的仿真模型。步骤如下:(1) 在MATLAB 的命令窗口运行simulink 命令,或单击工具栏中的图标,就可以打开Simulink模块库浏览器(Simulink Library Brows…...