主頁 > 企業開發 > react 性能優化

react 性能優化

2021-12-06 22:29:55 企業開發

react 性能優化

React 組件性能優化的核心就是減少渲染真實DOM節點的頻率,減少Virtual DOM 對比的頻率,以此來提高性能

1. 組件卸載之前進行清理操作

在組件中為window 注冊的全域事件,以及定時器,在組件卸載前要清理掉,防止組件卸載后繼續執行影回應用性能

我們開啟一個定時器然后卸載組件,查看組件中的定時器是否還在運行 Test 組件來開啟一個定時器

import {useEffect} from 'react'

export default function Test () {
  useEffect(() => {
    setInterval(() => {
      console.log('定時器開始執行')
    }, 1000)
  }, [])
  return <div>Test</div>
}

在App.js中引入定時器組件然后用flag變數來控制渲染和卸載組件

import Test from "./Test";
import { useState } from "react"
function App() {
  const [flag, setFlag] = useState(true)
  return (
    <div>
      { flag && <Test /> }
      <button onClick={() => setFlag(prev => !prev)}>點擊按鈕</button>
    </div>
  );
}

export default App;

在瀏覽器中我們去點擊按鈕發現組件被卸載后定時器還在執行,這樣組件太多之后或者這個組件不停的渲染和卸載會開啟很多的定時器,我們應用的性能肯定會被拉垮,所以我們需要在組建卸載的時候去銷毀定時器,

import {useEffect} from 'react'

export default function Test () {
  useEffect(() => {
    // 因為要銷毀定時器所以我們需要用一個變數來接受定時器id
    const InterValTemp =  setInterval(() => {
      console.log('定時器開始執行')
    }, 1000)
    return () => {
      console.log(`ID為${InterValTemp}定時器被銷毀了`)
      clearInterval(InterValTemp)
    }
  }, [])
  return <div>Test</div>
}

這個時候我們在去點擊銷毀組建的時候定時器就被銷毀掉了

2. 類組件用純組件來提升組建性能PureComponent

1. 什么是純組件

? 純組件會對組建的輸入資料進行淺層比較,如果輸入資料和上次輸入資料相同,組建不會被重新渲染

2. 什么是淺層比較

? 比較參考資料型別在記憶體中的參考地址是否相同,比較基本資料型別的值是否相同

3. 如何實作純組件

? 類組件集成 PureComponent 類,函陣列件使用memo方法

4. 為什么不直接進行diff操作,而是要進行淺層比較,淺層比較難到沒有性能消耗嗎

? 和進行 diff 比較操作相比,淺層比較小號更少的性能,diff 操作會重新遍歷整個 virtualDOM 樹,而淺層比較只比較操作當前組件的 state和props

在狀態中存盤一個name為張三的,在組建掛載后我們每隔1秒更改name的值為張三,然后我們看純組件和非純組件,查看結果

// 純組件
import { PureComponent } from 'react'
class PureComponentDemo extends PureComponent {
  render () {
    console.log("純組件")
    return <div>{this.props.name}</div>
  }
}
// 非純組件
import { Component } from 'react'
class ReguarComponent extends Component {
 render () {
   console.log("非純組件")
   return <div>{this.props.name}</div>
 }
}

引入純組件和非純組件 并在組件掛在后開啟定時器每隔1秒更改name的值為張三

import { Component } from 'react'
import { ReguarComponent, PureComponentDemo } from './PureComponent'
class App extends Component {
  constructor () {
    super()
    this.state = {
      name: '張三'
    }
  }
  updateName () {
    setInterval(() => {
      this.setState({name: "張三"})
    }, 1000)
  }
  componentDidMount () {
    this.updateName()
  }
  render () {
    return <div>
      <ReguarComponent name={this.state.name}></ReguarComponent>
      <PureComponentDemo name={this.state.name}></PureComponentDemo>
    </div>
  }
}

打開瀏覽器查看執行結果

image-20210922214700974

我們發現純組件只執行了一次,以后在改相同的值的時候,并沒有再重新渲染組件,而非純組件則是每次更改都在重新渲染,所以純組件要比非純組件更節約性能

3. 函陣列件來實作純組件 memo

  1. memo 基本使用

    將函陣列件變成純組件,將當前的props和上一次的props進行淺層比較,如果相同就組件組件的渲染,》,

我們在父組件中維護兩個狀態,index和name 開啟定時器讓index不斷地發生變化,name傳遞給子組件,查看父組件更新子組件是否也更新了, 我們先不用memo來查看結果

import { useState, useEffect } from 'react'
function App () {
  const [ name ] = useState("張三")
  const [index, setIndex] = useState(0)

  useEffect(() => {
    setInterval (() => {
      setIndex(prev => prev + 1)
    }, 1000)
  }, [])

  return <div>
    {index}
    <ShowName name={name}></ShowName>
  </div>
}

function ShowName ({name}) {
  console.log("組件被更新")
  return <div>{name}</div>
}

打開瀏覽器查看執行結果

image-20210923231543043

在不使用 memo 來把函陣列件變成純組件的情況下我們發現子組件隨著父組件更新而一起重新渲染,但是它依賴的值并沒有更新,這樣浪費了性能,我們使用 memo 來避免沒必要的更新

import { useState, useEffect, memo } from 'react'

const ShowName = memo(function ShowName ({name}) {
  console.log("組件被更新")
  return <div>{name}</div>
})

function App () {
  const [ name ] = useState("張三")
  const [index, setIndex] = useState(0)

  useEffect(() => {
    setInterval (() => {
      setIndex(prev => prev + 1)
    }, 1000)
  }, [])

  return <div>
    {index}
    <ShowName name={name}></ShowName>
  </div>
}

我們再次打開瀏覽器查看執行結果

image-20210922222640420

現在index變動 子組件沒有重新渲染了,用 memo 把組件變為純組件之后就避免了依賴的值沒有更新卻跟著父組件一起更新的情況

4. 函陣列件來實作純組件(為memo方法傳遞自定義比較邏輯)

memo 方法也是淺層比較

memo 方法是有第二個引數的第二個引數是一個函式

這個函式有個兩個引數,第一個引數是上一次的props,第二個引數是下一個props

這個函式回傳 false 代表重新渲染, 回傳true 重新渲染

比如我們有員工姓名和職位兩個資料,但是頁面中只使用了員工姓名,那我們只需要觀察員工姓名發生變動沒有,所以我們在memo的第二個引數去比較是否需要重新渲染

import { useState, useEffect, memo } from 'react'

function compare (prevProps, nextProps) {
  if (prevProps.person.name !== nextProps.person.name) {
    return false
  }
  return true
}

const ShowName = memo(function ShowName ({person}) {
  console.log("組件被更新")
  return <div>{person.name}</div>
}, compare)

function App () {
  const [ person, setPerson ] = useState({ name: "張三", job: "工程師"})

  useEffect(() => {
    setInterval (() => {
      setPerson({
        ...person,
        job: "挑糞"
      })
    }, 1000)
  }, [person])

  return <div>
    <ShowName person={person}></ShowName>
  </div>
}

5. shouldComponentUpdata

純組件只能進行淺層比較,要進行深層次比較,使用 shouldComponentUpdate,它用于撰寫自定義比較邏輯

回傳true 重新渲染組件, 回傳 false 組件重新渲染組件

函式的第一個引數為 nextProps,第二個引數為NextState

比如我們有員工姓名和職位兩個資料,但是頁面中只使用了員工姓名,那我們只需要觀察員工姓名發生變動沒有,利用shouldComponentUpdata來控制只有員工姓名發生變動才重新渲染組件,我們查看使用 shouldComponentUpdata 生命周期函式和不使用shouldComponentUpdata生命周期函式的區別

// 沒有使用的組件
import { Component } from 'react'
class App extends Component {
  constructor () {
    super()
    this.state = {
      person: {
        name: '張三',
        job: '工程師'
      }
    }
  }
  componentDidMount (){
    setTimeout (() => {
      this.setState({
        person: {
          ...this.state.person,
          job: "修水管"
        }
      })
    }, 2000) 
  }
  render () {
    console.log("render 方法執行了")
    return <div>
      {this.state.person.name}
    </div>
  }
}

我們打開瀏覽器等待兩秒

image-20210922220251277

發現render方法執行了兩次,組件被重新渲染了,但是我們并沒有更改name 屬性,所以這樣浪費了性能,我們用shouldComponentUpdata生命周期函式來判斷name是否發生了改變

import { Component } from 'react'
class App extends Component {
  constructor () {
    super()
    this.state = {
      person: {
        name: '張三',
        job: '工程師'
      }
    }
  }
  componentDidMount (){
    setTimeout (() => {
      this.setState({
        person: {
          ...this.state.person,
          job: "修水管"
        }
      })
    }, 2000) 
  }
  render () {
    console.log("render 方法執行了")
    return <div>
      {this.state.person.name}
    </div>
  }
  shouldComponentUpdate (nextProps, nextState) {
    if (this.state.person.name !== nextState.person.name) {
      return true;
    }
    return false;
  }
}

我們再打開瀏覽器等待兩秒之后

image-20210922220711461

我們只改變了job 的時候render方法只執行了一次,這樣就減少了沒有必要的渲染,從而節約了性能

6. 使用組件懶加載

使用路由懶加載可以減少bundle檔案大小,從而加快組建呈遞速度

創建 Home 組建

// Home.js
function Home() {
  return (
    <div>
      首頁
    </div>
  )
}

export default Home

創建 List 組建

// List.js
function List() {
  return (
    <div>
      串列頁
    </div>
  )
}

export default List

從react-router-dom包中引入 BrowserRouter, Route, Switch, Link 和 home 與list 來創建路由規則以及切換區域和跳轉按鈕

import { BrowserRouter, Route, Switch, Link } from 'react-router-dom'
import Home from './Home';
import List from './List';

function App () {
  return <div>
    <BrowserRouter>
        <Link to="/">首頁</Link>
        <Link to="/list">串列頁</Link>
      <Switch>
          <Route path="/" exact component={Home}></Route>
          <Route path="/list" component={List}></Route>
      </Switch>
    </BrowserRouter>
  </div>
}

使用 lazy, Suspense 來創建加載區域與加載函式

import { lazy, Suspense } from 'react';
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom'

const Home = lazy(() => import('./Home'))
const List = lazy(() => import('./List'))

function Loading () {
  return <div>loading</div>
}

function App () {
  return <div>
    <BrowserRouter>
        <Link to="/">首頁</Link>
        <Link to="/list">串列頁</Link>
      <Switch>
        <Suspense fallback={<Loading />}>
          <Route path="/" exact component={Home}></Route>
          <Route path="/list" component={List}></Route>
        </Suspense>
      </Switch>
    </BrowserRouter>
  </div>
}

使用注解方式來為打包后的檔案命名

const Home = lazy(() => import(/* webpackChunkName: "Home"  */'./Home'))
const List = lazy(() => import(/* webpackChunkName: "List" */'./List'))

7. 根據條件進行組件懶加載

適用于組件不會隨條件頻繁切換

import { lazy, Suspense } from 'react';


function App () {
  let LazyComponent = null;
  if (false){
    LazyComponent = lazy(() => import(/* webpackChunkName: "Home"  */'./Home'))
  } else {
    LazyComponent = lazy(() => import(/* webpackChunkName: "List" */'./List'))
  }
  return <div>
    <Suspense fallback={<div>loading</div>}>
      <LazyComponent />
    </Suspense>
  </div>
}

export default App;

這樣就只會加載一個組件從而提升性能

8. 通過使用占位符標記提升React組件的渲染性能

React組件中回傳的jsx如果有多個同級元素必須要有一個共同的父級

function App () {
  return (<div>
    	<div>1</div>
      <div>2</div>
    </div>)
}

為了滿足這個條件我們通常會在外面加一個div,但是這樣的話就會多出一個無意義的標記,如果每個元素都多處這樣的一個無意義標記的話,瀏覽器渲染引擎的負擔就會加劇

為了解決這個問題,React 推出了 fragment 占位符標記,使用占位符編輯既滿足了共同父級的要求,也不會渲染一個無意義的標記

import { Fragment } from 'react'
function App () {
  return <Fragment>
  		<div>1</div>
    	<div>1</div>
  </Fragment>
}

當然 fragment 標記還是太長了,所以有還有簡寫方法

function App () {
  return <>
  		<div>1</div>
    	<div>1</div>
  </>
}

9. 不要使用行內函式定義

在使用行內函式后,render 方法每次運行后都會創建該函式的新實體,導致 React 在進行 Virtual DOM 對比的時候,新舊函式比對不相等,導致 React 總是為元素系結新的函式實體,而舊的函式有要交給垃圾回收器處

import { Component } from 'react'
class App extends Component {
  constructor () {
    super()
    this.state = {
      name: '張三'
    }
  }
  render () {
    return <div>
      <h3>{this.state.name}</h3>
      <button onClick={() => { this.setState({name: "李四"})}}>修改</button>
    </div>
  }
}


export default App;

修改為以下的方式

import { Component } from 'react'
class App extends Component {
  constructor () {
    super()
    this.state = {
      name: '張三'
    }
  }
  render () {
    return <div>
      <h3>{this.state.name}</h3>
      <button onClick={this.setChangeName}>修改</button>
    </div>
  }
  setChangeName = () => {
    this.setState({name: "李四"})
  }
}

10. 在建構式中進行函式this系結

在類組件中如果使用 fn(){} 這種方式定義函式,函式的 this 指向默認只想 undefined,也就是說函式內部的 this 指向需要被更正,

可以在建構式中對函式進行 this 更正,也可以在內部進行更正,兩者看起來沒有太大差別,但是對性能影響是不同的

import { Component } from 'react'
class App extends Component {
  constructor () {
    super()
    this.state = {
      name: '張三'
    }
    // 這種方式應為構造器只會執行一次所以只會執行一次
    this.setChangeName = this.setChangeName.bind(this)
  }
  render () {
    return <div>
      <h3>{this.state.name}</h3>
      {/* 這種方式在render方法執行的時候就會生成新的函式實體 */}
      <button onClick={this.setChangeName.bind(this)}>修改</button>
    </div>
  }
  setChangeName() {
    this.setState({name: "李四"})
  }
}

在建構式中更正this指向只會更正一次,而在render方法中如果不更正this指向的話 那么就是 undefined ,但是在render方法中更正的話render方法的每次執行都會回傳新的函式實體這樣是對性能是有所影響的

11. 類組件中的箭頭函式

在類組件中使用箭頭函式不會存在this指向問題,因為箭頭函式不系結this

import { Component } from 'react'
class App extends Component {
  constructor () {
    super()
    this.state = {
      name: '張三'
    }
  }
  render () {
    return <div>
      <h3>{this.state.name}</h3>
      {/* <button onClick={() => { this.setState({name: "李四"})}}>修改</button> */}
      <button onClick={this.setChangeName}>修改</button>
    </div>
  }
  setChangeName = () => {
    this.setState({name: "李四"})
  }
}

箭頭函式在this指向上確實比較有優勢

但是箭頭函式在類組件中作為成員使用的時候,該函式會被添加成實體物件屬性,而不是原型物件屬性,如果組件被多次重用,每個組件實體都會有一個相同的函式實體,降低了函式實體的可用性造成了資源浪費

綜上所述,我們得出結論,在使用類組件的時候還是推薦在建構式中通過使用bind方法更正this指向問題

12. 避免使用行內樣式屬性

當使用行內樣式的時候,行內樣式會被編譯成JavaScript代碼,通過javascript代碼將樣式規則映射到元素身上,瀏覽器就會畫更多的時間執行腳本和渲染UI,從而增加了組件的渲染時間

function App () {
  return <div style={{backgroundColor: 'red';}}></div>
}

在上面的組件中,為元素增加了背景顏色為紅色,這個樣式為JavaScript物件,背景顏色需要被轉換成等效的css規則,然后應用到元素上,這樣涉及了腳本的執行,實際上行內樣式的問題在于是在執行的時候為元素添加樣式,而不是在編譯的時候為元素添加樣式

更好的方式是匯入樣式檔案,能通過css直接做的事情就不要通過JavaScript來做,因為JavaScript操作 DOM 非常慢

13. 優化條件渲染以提升組件性能

頻繁的掛在和卸載組件是一件非常耗性能的事情,應該減少組件的掛載和卸載次數,

在React中 我們經常會通過不同的條件渲染不同的組件,條件渲染是一必須做的優化操作.

function App () {
  if (true) {
    return <div>
      <Component1 />
    	<Component2 />
      <Component3 />
  	</div>
  } else {
    return <div>
        <Component2 />
      	<Component3 />
    </div>
  }
  
}

上面的代碼中條件不同的時候,React 內部在進行Virtual DOM 對比的時候發現第一個元素和第二個元素都已經發生變化,所以會卸載組件1、組件2、組件3,然后再渲染組件2、組件3,實際上變化的只有組件1,重新掛在組件2和組件3時沒有必要的

function App () {
  if (true) {
    return <div>
      { true && <Component1 />}
    	<Component2 />
      <Component3 />
  	</div>
  }
}

這樣變化的就只有組件1了節省了不必要的渲染

16. 避免重復的無限渲染

當應用程式狀態更改的時候,React 會呼叫 render方法 如果在render方法中繼續更改應用程式狀態,就會發生遞回呼叫導致應用報錯

image-20210923220549762

未捕獲錯誤:超出最大更新深度,當組件在componentWillUpdate或componentDidUpdate內重復呼叫setState時,可能會發生這種情況,React限制嵌套更新的數量以防止無限回圈,React限制的最大次數為50次

import { Component } from 'react'
class App extends Component {
  constructor () {
    super()
    this.state = {
      name: '張三'
    }
  }
  render () {
    this.setState({name:"張五"})
    return <div>
      <h3>{this.state.name}</h3>
      <button onClick={this.setChangeName}>修改</button>
    </div>
  }
  setChangeName = () => {
    this.setState({name: "李四"})
  }
}

與其他生命周期函式不同,render 方法應該被作為純函式,這意味著,在render方法中不要做以下事情

  1. 不要呼叫 setState 方法去更改狀態、
  2. 不要使用其他手段查詢更改 DOM 元素,以及其他更改應用程式的操作、
  3. 不要在componentWillUpdate生命周期中重復呼叫setState方法更改狀態、
  4. 不要在componentDidUpdate生命周期中重復呼叫setState方法更改狀態、

render方法執行根據狀態改變執行,這樣可以保持組件的行為與渲染方式一致

15. 為組件創建錯誤邊界

默認情況下,組件渲染錯誤會導致整個應用程式中斷,創建錯誤邊界可以確保組件在發生錯誤的時候應用程式不會中斷,錯誤邊界是一個React組件,可以捕獲子級組件在渲染是發生錯誤,當錯誤發生時,可以記錄下來,可以顯示備用UI界面,

錯誤邊界涉及到兩個生命周期,分別是 getDerivedStateFromError 和 componentDidCatch.

getDerivedStateFromError 為靜態方法,方法中需要回傳一個物件,該物件會和state物件進行合并,用于更改應用程式狀態.

componentDidCatch 方法用于記錄應用程式錯誤資訊,該方法回傳的是錯誤物件

import { Component } from 'react'
class App extends Component {
  constructor () {
    super()
    this.state = {
      hasError: false
    }
  }
  componentDidCatch (error) {
    console.log(error)
  }
  static getDerivedStateFromError () {
    return {
      hasError: true
    }
  }
  render () {
    if (this.state.hanError) {
      return <div>
        發生錯誤了
      </div>
    }
    return <Test></Test>
  }
}

class Test extends Component {
  constructor () {
    super()
    this.state = {
      hanError: false
    }
  }
  render () {
    throw new Error("發生了錯誤");
    return <div>
      正確的
    </div>
  }
}

當我們拋出錯誤的時候,getDerivedStateFromError 會合并回傳的物件到state 所以hasError會變成true 就會渲染我們備用的界面了

注意: getDerivedStateFromError 不能捕獲異步錯誤,譬如按鈕點擊事件發生后的錯誤

16. 避免資料結構突變

組件中 props 和 state 的資料結構應該保持一致,資料結構突變會導致輸出不一致

import { Component } from 'react'
class App extends Component {
  constructor () {
    super()
    this.state = {
      man: {
        name: "張三",
        age: 18
      }
    }
    this.setMan = this.setMan.bind(this)
  }
  render () {
    const { name, age } = this.state.man
    return <div>
      <p>
        {name}
        {age}
      </p>
      <button onClick={this.setMan}>修改</button>
    </div>
  }
  setMan () {
    this.setState({
      ...this.state,
      man: {
        name: "李四"
      }
    })
  }
}

乍一看這個代碼貌似沒有問題,仔細一看我們發現,在我們修改了名字之后年齡欄位丟失了,因為資料突變了 ,我們應該去避免這樣的資料突變

import { Component } from 'react'
class App extends Component {
  constructor () {
    super()
    this.state = {
      man: {
        name: "張三",
        age: 18
      }
    }
    this.setMan = this.setMan.bind(this)
  }
  render () {
    const { name, age } = this.state.man
    return <div>
      <p>
        {name}
        {age}
      </p>
      <button onClick={this.setMan}>修改</button>
    </div>
  }
  setMan () {
    this.setState({
      man: {
        ...this.state.man,
        name: "李四"
      }
    })
  }
}

17. 依賴優化

在應用程式中我們經常使用地三方的包,但我們不想參考包中的所有代碼,我們只想用到那些代碼就包含那些代碼,此時我們可以使用插件對依賴項進行優化

我們使用 lodash 舉例子. 應用基于 create-react-app 腳手架創建

1. 下載依賴

npm install react-app-rewired customize-cra lodash babel-plugin-lodash

react-app-rewired: 覆寫create-react-app 配置

module.exports = function (oldConfig) {
  	return	newConfig
}

customize-cra: 匯出輔助方法,可以讓以上寫法更簡潔

const { override, useBabelRc } = require("customize-cra")
module.exports = override(
	(oldConfig) => newConfig,	
  (oldConfig) => newConfig,
)

override: 可以接收多個引數,每個引數都是一個配置函式,函式接受oldConfig,回傳newConfig

useBabelRc:允許使用.babelrc 檔案進行babel 配置

babel-plugin-lodash:對lodash 進行精簡

2. 在專案的根目錄新建 config-overrides.js 并加入以下配置

const { override, useBabelRc } = require("customize-cra")

module.exports = override(useBabelRc())

3. 修改package.json檔案中的構建命令

{
  "script": {
       "start": "react-app-rewired start",
       "build": "react-app-rewired build",
       "test": "react-app-rewired test --env=jsdom",
       "eject": "react-scripts eject"
  }
}

4. 創建 .babelrc 檔案并加入配置

{
  "plugins": ["lodash"]
}

5. 生產環境下的三種 JS檔案

  1. main.[hash].chunk.js:這是你的應用程式代碼,App.js 等.
  2. 1.[hash].chunk.js:這是第三方庫的代碼,包含你在 node_modules 中匯入的模塊.
  3. runtime~main.[hash].js:webpack 運行時代碼.

6. App 組件中代碼

import _ from 'lodash'

function App () {
   console.log(_.chunk(['a', 'b', 'c', 'd']))
  return	<div>Test</div>
}

沒有引入lodash
沒有引入lodash

引入lodash
引入lodash

優化后的
優化后的

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

標籤:JavaScript

上一篇:超基礎的機器學習入門-原理篇

下一篇:基于ES6提供的回呼函式異步編程優化

標籤雲
其他(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