主頁 > 企業開發 > antd 3.x升4.x踩坑之路~

antd 3.x升4.x踩坑之路~

2023-02-01 07:54:18 企業開發

我們是袋鼠云數堆疊 UED 團隊,致力于打造優秀的一站式資料中臺產品,我們始終保持工匠精神,探索前端道路,為社區積累并傳播經驗價值,

兼容性問題

第三方依賴兼容問題

  • React - 最低 v16.9,部分組件使用 hooks 重構 react升級相關檔案
  • 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 請完全剔除對該過渡包的依賴

升級步驟(只有一步)

1、@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

codemod_error.png
上圖這類報錯是 Icon 組件自動替換錯誤,有 2 種處理方式:

  1. 報錯檔案的 Icon 比較少的情況,可以直接手動替換該檔案中的 Icon 組件,具體替換成 Icon 中的哪個組件可以根據 type 在 Icon檔案 中找,

  2. 下圖中是具體報錯的節點,可以看到 JSXSpreadAttribute 節點也就是拓展運算子中沒有 name 屬性,所以把 Icon 組件的拓展運算子改一下再執行替換腳本就可以了

    JSXSpreadAttribute.png

antd4 問題修復

styled-components

styled-components 依賴需要轉換寫法

image.png

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

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>

<Form
  ref={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 方法,
// antd v4
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,否則就會出現下面的情況,會有留白占位的情況
image.png

validateTrigger

onBlur 時不再修改選中值,且回傳 React 原生的 event 物件,
如果你在使用兼容包的 Form 且配置了 validateTriggeronBlur ,請改至 onChange 以做兼容,

validator

在 antd3 時,我們使用 callback 回傳報錯,但是 antd4 對此做了修改,自定義校驗,接收 Promise 作為回傳值,示例參考
image.png

  • antd3 的寫法
<FormItem label="具體時間" {...formItemLayout}>
  {getFieldDecorator('specificTime', {
    rules: [
      {
        required: true,
        validator: (_, value, callback) => {
          if (!value || !value.hour || !value.min) {
             return callback('具體時間不可為空');
          }
          callback();
        },
      },
    ],
  })(<SpecificTime />)}
</FormItem>
  • antd4 的寫法
<FormItem
  label="具體時間"
  {...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 拿到的資料是陣列時,例如這樣:

image.png

我們可以設定為這樣

const formItems = keys.map((k: React.Key) => (
  <Form.Item key={k} required label="名稱">
    <Form.Item
      noStyle
      name={['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

image.png
image.png

extra

image.png

<FormItem
  label="過濾條件"
  extra={
    <Tooltip title={customSystemParams}>
      系統引數配置&nbsp;
       <QuestionCircleOutlined />
     </Tooltip>
   }
>
  <Input.TextArea />
</FormItem>

Select

rc-select

底層重寫

  • 解決些許歷史問題
    • rc-select & rc-select-tree 的 inputValue & searchValue 之爭
      rc-select-tree 是 rc-select 結合 tree 寫的一個組件,相似但又不同,searchValue 就是其中一點,也不是沒人提過 issue,只是人的忘性很大,時間長了就忘了,混了,導致在 rc-select 中甚至出現了 searchValue 的字樣
    • inputValue 歷史問題,this.state.inputValue
      rc-select-inputvalue.jpg
      也不是不想改,只是改了之后改出了一堆 bug,真真應了一句話,每一個歷史包袱的存在,都有他存在的原因,,
    • onSelect 清空了值,又會被 onChange 賦值回來
  • 模塊復用

在新版的 rc-select 中,antd 官方抽取了一個 generator 方法,它主要接收一個 OptionList 的自定義組件用于渲染下拉框部分,這樣我們就可以直接復用選擇框部分的代碼,而自定義 Select 和 TreeSelect 對應的串列或者樹形結構了,

labelInValue

在 3.x 版本為

在 4.x 版本為

Table

fixed

table-fixed.jpg
固定列時,文字過長導致錯位的問題,被完美解決了,??ヽ(°▽°)ノ?

歷史原因

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 寬度被擠壓了,

image.png

解決方案

通過在 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 組件,和請求串列介面的引數

image.png

<Table
  rowKey="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

<Table
  rowKey="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 做處理可能導致切頁失敗,看下面代碼就明白了,寫的時候稍微注意一下即可,

image.png

table sorter columnKey

image.png

問題描述

表格中如果要對表格某一欄位進行排序需要在 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');
}}

image.png

Tree

Tree 組件取消 value 屬性,現在只需要添加 key 屬性即可

特別注意, 此問題會導致功能出問題,需要重點關注!!!

在專案中經常在 TreeItem 中增加引數,如:<TreeItem value=https://www.cnblogs.com/dtux/archive/2023/01/31/{value} data={data} >,在拖拽等回呼中就可以通過 nodeData.props.data的方式獲取到 data 的值,
但在 antd4 中,獲取引數的資料結構發生了改變,原先直接通過 props 點出來的不行了,
有兩種方式取值

  1. 不使用props,直接采用 nodeData.data 的方式,也可以直接拿到
  2. 繼續使用 props,在antd4中,還是可以通過 props 找到引數,只不過 antd 會把所有引數使用 data 進行包裹,就需要改成 nodeData.props.data.data

新版資料結構如下:

image.png

drag

拖拽節點位置的確定與 3.x 相比進行了變更,官網并沒有說明,具體如下圖

image.png
左側為 3.x,右側為 4.x,
在3.x版本,只要把節點拖拽成目標節點的上中下,即代表著目標節點的同級上方,子集,同級下方

在 4.x 版本,是根據當前拖拽節點與目標節點的相對位置進行確定最終的拖拽結果,
當拖拽節點處于目標節點的下方,且相對左側對齊的位置趨近于零,則最終的位置為目標節點的同級下方,

image.png

當拖拽節點處于目標節點的下方,且相對左側一個縮近的位置,則最終的位置為目標節點的子集,

image.png

當拖拽節點處于目標節點的上方,且相對左側對齊的位置趨近于零,則最終的位置為目標節點的同級上方,

image.png

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 失效

image.png

Button

在 antd 3.0 中危險按鈕采用 type

image.png

使用如下:
設計改動點 type、dangr 屬性

image.png

Tabs

使標簽頁不被選中

// 3.x
activeKey={undefined}
// 4.x
activeKey={null}

總結

該篇文章詳細講解了如何從 antd3 升級到 antd4 其中的步驟,以及團隊在實踐程序中發現的一些問題和對應的解決方案,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/542739.html

標籤:其他

上一篇:如何手動補充陳年老庫(或純 JS 代碼)的 TypeScript 型別?

下一篇:DNS 是如何影響你沖浪速度的?網路干貨

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more