React+Antd+TypeScript 规范整合

1.TypeScript代码标准化规则

提取出部分适用于项目中的官方要求的的TypeScript用于约束贡献者的编码规范 [typescript官方规范]
出自:深圳市伙伴行网络科技有限公司 编辑:前端开发-毛昱宇

(https://zhongsp.gitbooks.io/typescript-handbook/doc/wiki/coding_guidelines.html?q=)

命名

  • 使用PascalCase为类型命名。
type ColumnProps = xxx
  • 不要使用I做为接口名前缀。(定义props和state 使用IProps / IState)
  • 使用PascalCase为枚举值命名。
  • 使用camelCase为函数命名。
const handleTableChange = ():void => xxx
  • 使用camelCase为属性或本地变量命名。
  • 不要为私有属性名添加_前缀。
  • 尽可能使用完整的单词拼写命名。

风格

  • 使用arrow函数(箭头函数)代替匿名函数表达式。
  • 只要需要的时候才把arrow函数的参数括起来。
    比如,(x) => x + x是错误的,下面是正确的做法:

    1. x => x + x
    2. (x,y) => x + y
    3. <T>(x: T, y: T) => x === y
  • 开大括号总是放在其关联语句的同一行(大括号不换行)。
  • 小括号里开始不要有空白.
    逗号,冒号,分号后要有一个空格。比如:

    1. for (var i = 0, n = str.length; i < 10; i++) { }
    2. if (x < 10) { }
    3. function f(x: number, y: string): void { }
  • 每个变量声明语句只声明一个变量
    (比如 使用 var x = 1; var y = 2; 而不是 var x = 1, y = 2;)。

类型

  • 除非类型/函数需要在多个组件中共享,否则不要导出(export)

  • 在文件中,类型定义应该放在顶部

null和undefined

  • 使用 undefined,不要使用 null

    typeof null == "object"
    

注释

  • 为函数,接口,枚举类型和类使用JSDoc风格的注释。JSDoc

2.React+antd+typescript代码规范

注释

使用 koroFileHeader 插件用于快速生成开发者注释。koroFileHeader是一款用于在vscode中用于生成文件头部注释和函数注释的插件,支持所有主流语言,功能强大,灵活方便,文档齐全。

  • 文件顶部的注释,包括描述、作者、日期、最后编辑时间,最后编辑人

    /** @Description: app im菜单配置列表中的表格模块* @Author: maoyuyu* @Date: 2019-08-05 10:31:12* @LastEditTime: 2019-08-14 17:08:33* @LastEditors: Please set LastEditors*/
    

    文件头部添加注释快捷键windowctrl+alt+i,macctrl+cmd+i

    在光标处添加函数注释windowctrl+alt+t,macctrl+cmd+t

    vscode setting 配置如下

    "fileheader.configObj": {"autoAdd": false, // 自动添加头部注释开启才能自动添加
    },
    "fileheader.customMade": {"Author":"[you name]","Date": "Do not edit", // 文件创建时间(不变)"LastEditors": "[you name]", // 文件最后编辑者"LastEditTime": "Do not edit", // 文件最后编辑时间"Description":""
    },
    "fileheader.cursorMode": {"Author":"[you name]","description": "", "param": "", "return":""
    }
    
  • 业务代码的注释

  • /*业务代码注释*/
    
  • 变量的注释

  • interface IState {// 名字name: string;// 电话phone: number;// 地址address: string;
    }
    
  • 公共方法/私有方法的注释

  • /*** 用于获取富文本通知的格式* @param formatContent 格式化后的content(后台返回)* @param useEdit 是否用于修改(true:修改通知的反显)*/
    getContent(formatContent:string, useEdit:boolean=false){try{return useEdit? formatContent : formatContent.replace(reg,'')}catch(err){return ""}
    }
    

引用组件顺序

  • 第三方组件库 ==> 公共组件 ==> 业务组件 ==>utils ==> map ==> css 样式

  • //react
    import * as React from "react"
    import { SFC } from "react"
    //dva
    import { connect } from "dva"
    import { Link } from 'dva/router';
    //antd
    import { Table,Dropdown, Menu,Button, Icon,Modal } from 'antd';
    import { ColumnProps } from "antd/lib/table/interface"
    //公共组件
    import { DefaultProps } from "@/interface/global"
    import { IMList } from "@/interface/Operations/AppImMenu/list"
    import { Pagination } from "@/interface/BrokersBusiness/BuildingManage/buildingList"
    import { appImModelAction } from "./model"
    //util
    import { parseQuery, } from '@/utils/utils';
    //map
    import { androidType, iosType } from "../common/maps"
    //less
    import styles from "./AppImMenuList.less"
    

引号

  • 使用双引号或es6反引号

命名

  • 同上typescript 代码标准化规则
  • 定义props 和 state 接口名以大写字母I为前缀
interface IProps extends DefaultProps {appNoticeModel: AppNoticeProps,officeTree: any[],
}interface IState {id?: number | null,uploading?: boolean,excludeControls?:BuiltInControlType[]
}

项目中关闭tslint中的interface以大写字母I为前缀的规则,认为会影响interface的阅读。前缀I的命名规则放在prop 和state的描述上,用于识别interface的作用。

  • 常量: 全大写风格,大写字母、数字和下划线,单词之间以下划线分隔,例如:ABC_TEST。禁止汉字、特殊符号、小写字母。同时以const 定义变量
const UPLOADURL:string = "/api/file/upload"

interface声明顺序

  • 日常用到比较多的是四种,只读参数放第一位,必选参数第二位,可选参数次之,不确定参数放最后
interface iProps {readonly x: number;readonly y: number;name: string;age: number;height?: number;[propName: string]: any;
}

state定义

  • 定义state前加上只读属性(readonly),用于防止无意间对state的直接修改,或者在constructor定义
readonly state = {id: null,imageList: [],smallImageList: [],uploading: false,}//constructorconstructor(props){super(props)this.state = {id: null,imageList: [],smallImageList: [],uploading: false,}
}

声明规范

  • 不要使用 var 声明变量(已加入tslint套餐)
  • 不会被修改的变量使用 const 声明(常量必须使用const声明)
  • 去除声明但未被引用的代码
  • 不允许有空的代码块

渲染默认值

  • 添加非空判断可以提高代码的稳健性,例如后端返回的一些值,可能会出现不存在的情况,应该要给默认值.
// bad
render(){{name}
}// good
render(){{!!name || '--'}
}/*=================================*/
// bad
this.setState({status: STATUS.READY,apps: list,total: totalCount,page: page,
});// good
const { list, totalCount } = await getPeopleList(keyword, page, pageSize);
this.setState({status: STATUS.READY,apps: list || [],total: totalCount || 0,page: page,
});

数据格式转换

  • 把字符串转整型可以使用+号
let maxPrice = +form.maxPrice.value;
let maxPrice = Number(form.maxPrice.value);
  • 转成 boolean 值用!!
let mobile = !!ua.match(/iPhone|iPad|Android|iPod|Windows Phone/);

使用 location 跳转前需要先转义

// bad
window.location.href = redirectUrl + '?a=10&b=20';// good
window.location.href = redirectUrl + encodeURIComponent('?a=10&b=20');

业务代码里面的异步请求需要 try catch

  • ajax 请求,使用 try catch,错误提示后端返回,并且做一些失败后的状态操作例如进入列表页,我们需要一个 loading 状态,然后去请求数据,可是失败之后,也需要把 loading 状态去掉,把 loading 隐藏的代码就写在 finally 里面。

    getStudentList = async () => {try {this.setState({loading: true,isEmpty: false});await getStudentList({});this.setState({loading: false,isEmpty: true});} catch (e) {// TODOconsole.log(e)} finally {//  失败之后的一些兜底操作this.setState({loading: false,isEmpty: true});}
    };
    

setState使用

  • 使用setState 函数的写法
//bad
this.setState({a:300
})//good
this.setState((state,props) => {return {a:300}}
)

原因:

//对象式
//state.count = 1
function incrementMultiple() {this.setState({count: this.state.count + 1});this.setState({count: this.state.count + 1});this.setState({count: this.state.count + 1});
}
//console.log(this.state.count) //2
//函数式
function increment(state, props) {return {count: state.count + 1};
}
function incrementMultiple() {this.setState(increment);this.setState(increment);this.setState(increment);
}
//console.log(this.state.count) //4

setState将要修改的值加入队列进行批量处理

function incrementMultiple() {this.setState({count: this.state.count + 1});this.setState({count: this.state.count + 1});this.setState({count: this.state.count + 1});
}//等同于
function incrementMultiple() {const count = this.state.countthis.setState({count: count + 1});this.setState({count: count + 1});this.setState({count: count + 1});
}

而函数式setState每次调用内部会获取上一次修改的值再批量更新

  • 避免使用setState同步情况
//bad
setTimeout(()=>{this.setState({info})
})

setState一般情况下为异步操作,只有当使用js原生方法调用时才会出现同步情况。setState同步不会批量处理修改,会造成性能降低。

判断

  • 使用定义好的常量代替type值的判断
// bad
if (type !== 0) {// TODO
}// good
const STATUS: Record<string, any> = {READY: 0,FETCHING: 1,FAILED: 2
};if (type === STATUS.READY) {// TODO
}// best
enum STATUS {// 就绪READY = 0,// 请求中FETCHING = 1,// 请求失败FAILED = 2,
}
  • 减少多个boolean值变量的联合判断?
if((type1 == 0 || type1 == 1) && type2 !== 0){pass
}

该代码判断冗余且难以维护,应维护成标识

/*** 用于根据type值判断是否显示附件和喜报*/
enum TypeFlag {Empty = 0,//type值为空ShowHapplyNews = 1,//type值为1ShowOther = 1 << 1//type值不为1,切type值存在
};//标识维护/控制器
private showUploadRule(type){let KEY = TypeFlag.Emptyif(type == 1){KEY |= TypeFlag.ShowHapplyNews}if(type && type !==1){KEY |= TypeFlag.ShowOther}if(type && type == 3){KEY &= ~TypeFlag.ShowOther}return KEY
}//判断是否有权限 (type == 1)
{this.showUploadRule(type) & TypeFlag.ShowOther ? <FormItem label="附件"  >...pass</FormITem>:null}

具体使用规则参见typescript枚举

公共组件开发规则

  • 目录
|- components|- component1|- index.tsx|- component1.tsx|- aaa.tsx|- bbb.tsx|- component2|- index.js|- component2.tsx|- aaa.tsx|- bbb.tsx|- ccc.tsx
//aaa.tsx
import * as React from "react"
...
export default class Aaa extends React.component<IProps, IState>{pass
}//component1.tsx
import * as React from "react"
import Aaa from "./aaa"
...export default class Component1 extends React.component<IProps, IState>{render {return (<Aaa>pass</Aaa>)}
}//index.tsx
import Component1 from "./component1"
export default Component1

代码过滤掉你没考虑到的情况

  • 例如一个函数,你只想操作字符串,那你必须在函数开头就只允许参数是字符串
function parse (str:string){if (typeof(str) === 'string' ) {}
}

####不再使用react 即将废弃的生命周期函数

componentWillMount
componentWillReceiveProps
componentWillUpdate//bad
componentWillMount(){formItemFun(this.props.form, map);
}//good 直接在构造函数中构造
constructor(props:IProps){super(props)formItemFun(this.props.form, map);
}

react17将会正式废弃这三个生命周期函数

for-in 中一定要有 hasOwnProperty 的判断(即禁止直接读取原型对象的属性)

//bad
const arr = [];
const key = '';for (key in obj) {arr.push(obj[key]);
}//good
const arr = [];
const key = '';for (key in obj) {if (obj.hasOwnProperty(key)) {arr.push(obj[key]);}
}//或者使用Object.keys()
for (key of Object.keys(obj)) {arr.push(obj[key]);
}

防止 xss 攻击

  • input,textarea 等标签,不要直接把 html 文本直接渲染在页面上,使用 xssb 等过滤之后再输出到标签上;
import { html2text } from 'xss';
render(){<divdangerouslySetInnerHTML={{__html: html2text(htmlContent)}}
/>
}

禁止使用 dangerouslySetInnerHTML属性

在组件中获取真实 dom

  • 使用 16 版本后的 createRef()函数
class MyComponent extends React.Component<iProps, iState> {constructor(props) {super(props);this.inputRef = React.createRef();}render() {return <input type="text" ref={this.inputRef} />;}componentDidMount() {this.inputRef.current.focus();}
}

使用私有属性取代state状态

  • 对于一些不需要控制ui的状态属性,我们可以直接绑到this上, 即私有属性,没有必要弄到this.state上,不然会触发渲染机制,造成性能浪费 例如请求翻页数据的时候,我们都会有个变量。
// bad
state: IState = {pageNo:1,pageSize:10
};// good
queryParams:Record<string,any> = {pageNo:1,pageSize:10
}

代码粒度

  • 超过两次使用的代码用函数分离
//判断是编辑/新增
isEdit = () => {return !!parseQuery(location.search).id || parseQuery(location.search).id == 0
}//提交表单
formSaveParams = (fieldsValue: FieldsValue) => {let formFieldsValue:FieldsValue & {edit?:boolean} = {...fieldsValue}if(this.isEdit()){formFieldsValue = {...formFieldsValue,id:this.state.id,edit:true}}return formFieldsValue
}render(){return (<PageHeaderWrapper title={`${this.isEdit() ? '编辑' : '添加'}IM配置`} content="请按照页面要求填写数据">pass</PageHeaderWrapper>)
}
  • 工具函数和业务逻辑抽离,表单校验和业务抽离、事件函数和业务抽离,ajax和业务抽离。
componentDidMount(){this.getList()
}       /*获取列表 */
getList = () => {const { form } = this.propsconst type = form.getFieldValue('type')const page = {currentPage: 1,pageRows: 10,}const formData = {type,}this.upDate(page, formData)}//ajax
upDate = (page, formData?) => {const { dispatch } = this.propsdispatch(appNoticeModelAction('fetchList')(payload));
}

if else 等判断太多了,后期难以维护

  • 抽离config.js 对配置进行统一配置
例如你的业务代码里面,会根据不同url参数,代码会执行不同的逻辑.
/info?type=wechat&uid=123456&
const qsObj = qs(window.location.url)
const urlType = qsObj.type
// bad
if (urlType === 'wechat') {doSomeThing()
} else if () {doSomeThing()
} else if () {doSomeThing()
} else if () {doSomeThing()
}// good
config.t
const urlTypeConfig: Record<string, typeItem> = {'wechat': { // key 就是对应的typename: 'wechat', show: ['header', 'footer', 'wechat'] // 展示什么,可能是异步的pession: ['admin'], // 权限是什么,可能是异步的},'zhifubao': { // key 就是对应的typename: 'zhifubao', show: ['header', 'footer', 'zhifubao'] // 展示什么,可能是异步的pession: ['admin'], // 权限是什么,可能是异步的},
}// 业务逻辑
const qsObj = qs(window.location.url)
const urlType = qsObj.type
urlTypeConfig.forEach(item => {if(urlType === item.type) {doSomeThing(item.show)}
})

3.使用接口对象类型

对于ant design 内置的拥有字段效验功能的类与接口需要强制在代码中使用

事件对象类型

ClipboardEvent<T = Element> 剪贴板事件对象
DragEvent<T = Element> 拖拽事件对象
ChangeEvent<T = Element> Change 事件对象
KeyboardEvent<T = Element> 键盘事件对象
MouseEvent<T = Element> 鼠标事件对象
TouchEvent<T = Element> 触摸事件对象
WheelEvent<T = Element> 滚轮事件对象
AnimationEvent<T = Element> 动画事件对象
TransitionEvent<T = Element> 过渡事件对象
import { MouseEvent } from 'react';interface IProps {onClick(event: MouseEvent<HTMLDivElement>): void;
}

Table

import { ColumnProps } from "antd/lib/table/interface"interface IMList {id: string;routeKey: string;routeValue: string;type: number;remark: string;createDate: string;updateDate: string;delFlag: number;
}const columns: Array<ColumnProps<IMList>> = [{title: <div className={styles.tableTeCenter}>路由key</div>,dataIndex: 'routeKey',fixed: tableWidth < 1470 ? 'left' : false,render: (val, item, index) => <div className={styles.tableCenter}>{index + 1}</div>,},{title: <div className={styles.tableTeCenter}>路由value</div>,dataIndex: 'routeValue',render: (val, item) => <div className={styles.tableCenter}>{`${val || ''}`}</div>,},{title: <div className={styles.tableTeCenter}>类型</div>,dataIndex: 'type',render: (val, item) => <div className={styles.tableCenter}>{renderFloor(val, item)}</div>,},{title: <div className={styles.tableTeCenter}>描述</div>,dataIndex: 'describe',render: (val, item) => (<div className={styles.tableCenter}>{renderHouseAreaPrice(val, item, 1)}</div>),},]

Form

  • 引入form的方法
import { FormComponentProps } from "antd/lib/form/Form";//内置form的属性和方法interface IProps extends DefaultProps, FormComponentProps {appNoticeModel: AppNoticeProps,officeTree: any[],
}

####表单字段效验

使用json2ts插件 可以直接通过json数据生成interface

  • 先通过接口文档的请求示例使用json2ts确定好FieldsValue接口。然后对表单提交fieldsValue字段进行校验
interface FieldsValue {id?:string|number,productId?:number,platform?:string,adLocation?:number,effectiveFrequency?:number,effectiveImmediately?:number,minVersion?:string,title?:string,imageUrl?:any,smallImageUrl?:any,jumpRouteId?:string,jumpRouteKey?:string,params?:Params,describe?:string,
}handleSubmit = () => {const { id } = this.stateconst { form, dispatch } = this.props;//确定fieldsValue对象为FieldsValue类型form.validateFields((err, fieldsValue: FieldsValue) => {if (err) returndispatch(appAdvModelAction('submitAdvForm')({...fieldsValue,id,}))})
}
  • 对Details处理
//interface.ts
export interface Detail {id?: string;type?: number;range?: number;otherRange?: string;effectiveImmediately?: number;isEffective?: number;title?: string;attchUrlList?: AttchUrl[];imageUrl?: string;content?: EditorState;clicks?: number;createTime?: number;activityTime?: number;officeId?: string;officeName?: string;createId?: string;createName?: string;
}//interface.ts
//页面需要的details类型,对接口返回的进行重写
export interface RenderDetail extends Omit<Detail,"imageUrl" | "attchUrlList"> {imageUrl?:{[key:string]:any},attchUrlList?:any
}//model.ts
//后台返回的details信息
export interface AppNoticeProps {detail:Detail,
}...reducers:{saveDetail(state,{ payload }){const processedDetail:RenderDetail = {...(payload as Detail) || null,content:BraftEditor.createEditorState(payload.content||""),imageUrl:defaultImg(payload.imageUrl),}return {...state,detail:processedDetail || {}}}}//page.tsx
interface IProps {detail:RenderDetail,
}export default Page extends React.Component<IProps,IState>{render(){return (<Form>...<EffectiveImmediately initValue={detail.effectiveImmediately}/></Form>)}
}

组件开发原则

单一职责原则(SPR)

  • 目录结构
|- components|- component1|- index.tsx|- component1.tsx|- aaa.tsx|- bbb.tsx|- component2|- index.js|- component2.tsx|- aaa.tsx|- bbb.tsx|- ccc.tsx

每个页面一个目录,通过入口index.tsx暴露出。遵循单一职责原则,component.tsx只负责数据ajax请求和提交。 单一职责原则(SPR)

Flux

  • dva设计遵循flux模型,view层只提交dispatch,model层负责action与store管理。因此数据操作应当尽量放在model层处理。
/*提交表单*/
//page.tsxhandleSubmit = () => {const { id } = this.stateconst { form, dispatch } = this.props;form.validateFields((err, fieldsValue: FieldsValue) => {if (err) returndispatch(appAdvModelAction('submitAdvForm')({...fieldsValue,id,}))})}//model.ts...effects:{*submitAdvForm({ payload }, { call, put }) {yield put({type: 'changeState',payload: {editLoading:true},});let processedPayload:FieldsValue = {...(payload as FieldsValue),params: payload.params.map(key => payload.paramsSave[key]),imageUrl: payload.imageUrl[0].saveUrl,smallImageUrl: payload.smallImageUrl[0].saveUrl,platform: payload.platform.join(","),}if(!processedPayload.id && processedPayload.id !==0) delete processedPayload.idconst res = yield call(adConfigSave, processedPayload);if(res.code == 200){message.success("保存成功")yield put(routerRedux.push(routerConfig('AppAdvMenuList')));  }else{message.error('保存失败,' + res.msg);}yield put({type: 'changeState',payload: {editLoading:false},});},}
/*获取详情*/
//page.tsx
...
render(){return (<Form>{/*默认值直接获取,不在页面中进行任何处理*/}<Platform initValue={detail.platform} allowClear={true}/><Params initValue={detail.params}  /><SmallImageUrl initValue={detail.smallImageUrl} /></Form>)
}//models.ts
...
reducers:{saveDetail(state,{ payload }){let processedPayload:Detail = {...(payload as Omit<FieldsValue,"id">),platform:payload.platform.split(",").map(k=>+k),jumpRoute:(payload.jumpRouteKey && payload.jumpRouteId) ? payload.jumpRouteKey + "&&" + payload.jumpRouteId : "",imageUrl:payload.imageUrl && defaultImg(payload.imageUrl),smallImageUrl:payload.smallImageUrl && defaultImg(payload.smallImageUrl)}return {...state,detail:processedPayload}}
}

数据与视图完全分离增加页面的复用性,不需要对每个接口返回的不同数据做不同的处理。同样model层数据使用纯js代码处理,降低与视图耦合,方便测试。也方便迁移,如后续使用node中间层做前端与服务端的完全解耦

其他

  • 按照之前发布的伙伴前端开发手册及出的规范配合进行

React+Antd+TypeScript 开发规范相关推荐

  1. typescript+react+antd基础环境搭建

    typescript+react+antd基础环境搭建(包含样式定制) tsconfig.json 配置 // 具体配置可以看上面的链接 这里module moduleResolution的配置都会影 ...

  2. 使用create-react-app搭建TypeScript+React+Ant Design开发环境

    一.使用create-react-app创建一个支持TypeScript+React的开发环境: 要创建一个支持TypeScript的Create React App项目,可以运行: npx crea ...

  3. React Native开发规范(非官方,自己定义的)

    React Native开发规范 一.命名规范 二.代码格式 三.注释规约 四.样式规约 五.Redux 相关操作 六.桥接规约 七.JSX 规约 八.组件规约 九.npm 规约 十.性能优化 一.命 ...

  4. React项目前端开发总结

    此项目为公司的公众号管理系统,承载了公司每个部门的业务,需求多,开发周期长,技术可圈可点之处较多,特此记录与大家分享! 1. 使用技术 react+react-router + react-redux ...

  5. React Hook + Typescript,实现高颜值在线记账本

    React 已经是 JavaScript 生态系统中最受欢迎的前端框架之一.尽管人们已经对它赞不绝口,但 React 团队仍然在努力让它变得更好. 在 2018 ReactConf 大会上,React ...

  6. javascript实战pdf_《TypeScript开发实战》总结

    <TypeScript开发实战>是极客时间上的课程,是由搜狗营销事业部高级架构师的梁宵老师出品,总共47章,涵盖了TypeScript所有用法,以及我们如何在实战中应用TS.本课程还覆盖了 ...

  7. React Native组件开发指南

    React Native的组件开发一直处在一个比较尴尬的处境.在官方未给予相关示例与脚手架的情况下,社区中依然诞生了许许多多的React Native组件.因为缺少示例与规范,很多组件库仅含有一个in ...

  8. Visual Studio Code搭建TypeScript开发环境

    转载 http://www.cnblogs.com/sunjie9606/p/5945540.html 使用Visual Studio Code搭建TypeScript开发环境 1.TypeScrip ...

  9. 前端开发规范文档(html,css,js)

    首先吐槽一句,本来想上传word文档的,可是发现博客不能上传word文档,这就很尴尬了. 首先声明该规范不是本人写的,网上搜前端规范发现这个很详细就先复制下来做笔记,当然不可能啥都按规范来,每个公司的 ...

最新文章

  1. Nginx下完美解决WordPress的伪静态 (wordpress 迁移后 导致 页面404)
  2. 通过一个简单的例子学习Angular Injection Token工作原理
  3. NPOI 菜鸟实践行之根据指定的模板生成Excel 2003格式的文件 (一)
  4. 前端开发者的福音!通过拖拽就可生成Vue代码的平台来了!
  5. 作者:程学旗(1972-),男,中国科学院计算技术研究所研究员、博士生导师、副所长,中国科学院网络数据科学与技术重点实验室主任。...
  6. 微信群接龙报名小程序功能模块源码V1.1.38
  7. 利用dao传值给mysql_koa+mysql+vue+socket.io全栈开发之数据访问篇
  8. R可能让您惊喜的10件事
  9. ElasticSearch安装分词插件IK
  10. 白盒分析CC网络验证
  11. 列出所有内核_Windows系统内核溢出漏洞提权
  12. VxWorks的漏洞分析与解决方案
  13. vs使用快捷键注销多行
  14. Java ques: Unknown initial character set index ‘255‘ received from server. Initial client character
  15. C语言程序设计——计算图形面积(圆形,矩形,三角形,梯形)
  16. 16. Spring boot 错误页面
  17. (二)PositionRank: An Unsupervised Approach to Keyphrase Extractionfrom Scholarly Documents解读一
  18. 金融类APP上架经验分享
  19. 关于uni-app中SegmentedControl 分段器不显示的问题
  20. 微信小程序例子——使用icon组件显示常用图标

热门文章

  1. Android下载网上图片
  2. 最全PLC输入输出各种回路接线
  3. 香港银行开户失败的原因及应对方法 香港银行开户要求愈发严资者如果想在香港银行开户,需对香港银行开户政透彻的了解,这样才能确保开户的成功率。
  4. 手机屏幕画面实时直播
  5. mysql 1032 update_解决mysql 1032 主从错误
  6. 设计模式之禅学习笔记
  7. 淘宝如何打造承载亿级流量的首页?
  8. 一年级下册计算机教学计划,新人教版一年级数学下册教学计划
  9. 特征工程与表示学习:人工 vs 自动
  10. HTML如何画一条分割线_div之间设置间隔