解析React?中的Virtual?DOM
React在前端界一直很流行,而且學(xué)起來(lái)也不是很難,只需要學(xué)會(huì)JSX、理解State和Props,然后就可以愉快的玩耍了,但想要成為React的專家你還需要對(duì)React有一些更深入的理解,希望本文對(duì)你有用。
React在前端界一直很流行,而且學(xué)起來(lái)也不是很難,只需要學(xué)會(huì)JSX、理解State
和Props
,然后就可以愉快的玩耍了,但想要成為React的專家你還需要對(duì)React有一些更深入的理解,希望本文對(duì)你有用。
這是Choerodon的一個(gè)前端頁(yè)面
在復(fù)雜的前端項(xiàng)目中一個(gè)頁(yè)面可能包含上百個(gè)狀態(tài),對(duì)React框架理解得更精細(xì)一些對(duì)前端優(yōu)化很重要。曾經(jīng)這個(gè)頁(yè)面點(diǎn)擊一條記錄展示詳情會(huì)卡頓數(shù)秒,而這僅僅是前端渲染造成的。
為了能夠解決這些問(wèn)題,開(kāi)發(fā)者需要了解React組件從定義到在頁(yè)面上呈現(xiàn)(然后更新)的整個(gè)過(guò)程。
React在編寫(xiě)組件時(shí)使用混合HTML
和JavaScript
的一種語(yǔ)法(稱為JSX)。 但是,瀏覽器對(duì)JSX及其語(yǔ)法一無(wú)所知,瀏覽器只能理解純JavaScript
,因此必須將JSX轉(zhuǎn)換為HTML
。 這是一個(gè)div的JSX代碼,它有一個(gè)類和一些內(nèi)容:
<div className='cn'> 文本 </div>
在React中將這段jsx變成普通的js之后它就是一個(gè)帶有許多參數(shù)的函數(shù)調(diào)用:
React.createElement( 'div', { className: 'cn' }, '文本' );
React.createElement( 'div', { className: 'cn' }, ['Content 1!', React.createElement('br'), 'Content 2!'] ) 它的第一個(gè)參數(shù)是一個(gè)字符串,對(duì)應(yīng)html中的標(biāo)簽名,第二個(gè)參數(shù)是它的所有屬性所構(gòu)成的對(duì)象,當(dāng)然,它也有可能是個(gè)空對(duì)象,剩下的參數(shù)都是這個(gè)元素下的子元素,這里的文本也會(huì)被當(dāng)作一個(gè)子元素,所以第三個(gè)參數(shù)是 `“文本”` 。 到這里你應(yīng)該就能想象這個(gè)元素下有更多`children`的時(shí)候會(huì)發(fā)生什么。 ```html <div className='cn'> 文本1 <br /> 文本2 </div>
React.createElement( 'div', { className: 'cn' }, '文本1', // 1st child React.createElement('br'), // 2nd child '文本1' // 3rd child )
目前的函數(shù)有五個(gè)參數(shù):元素的類型,全部屬性的對(duì)象和三個(gè)子元素。 由于一個(gè)child
也是React已知的HTML
標(biāo)簽,因此它也將被解釋成函數(shù)調(diào)用。
到目前為止,本文已經(jīng)介紹了兩種類型的child
參數(shù),一種是string
純文本,一種是調(diào)用其他的React.createElement
函數(shù)。其實(shí),其他值也可以作為參數(shù),比如: - 基本類型 false,null,undefined和 true - 數(shù)組 - React組件
使用數(shù)組是因?yàn)榭梢詫⒆咏M件分組并作為一個(gè)參數(shù)傳遞:
當(dāng)然,React的強(qiáng)大功能不是來(lái)自`HTML`規(guī)范中描述的標(biāo)簽,而是來(lái)自用戶創(chuàng)建的組件,例如:
```js function Table({ rows }) { return ( <table> {rows.map(row => ( <tr key={row.id}> <td>{row.title}</td> </tr> ))} </table> ); }
組件允許開(kāi)發(fā)者將模板分解為可重用的塊。在上面的“純函數(shù)”組件的示例中,組件接受一個(gè)包含表行數(shù)據(jù)的對(duì)象數(shù)組,并返回React.createElement
對(duì)table元素及其行作為子元素的單個(gè)調(diào)用 。
每當(dāng)開(kāi)發(fā)者將組件放入JSX布局中時(shí)它看上去是這樣的:
<Table rows={rows} />
但從瀏覽器角度,它看到的是這樣的:
React.createElement(Table, { rows: rows });
請(qǐng)注意,這次的第一個(gè)參數(shù)不是以string
描述的HTML元素,而是組件的引用(即函數(shù)名)。第二個(gè)參數(shù)是傳入該組件的props
對(duì)象。
將組件放在頁(yè)面上
現(xiàn)在,瀏覽器已經(jīng)將所有JSX組件轉(zhuǎn)換為純JavaScript
,現(xiàn)在瀏覽器獲得了一堆函數(shù)調(diào)用,其參數(shù)是其他函數(shù)調(diào)用,還有其他函數(shù)調(diào)用……如何將它們轉(zhuǎn)換為構(gòu)成網(wǎng)頁(yè)的DOM元素?
為此,開(kāi)發(fā)者需要使用ReactDOM
庫(kù)及其render
方法:
function Table({ rows }) { /* ... */ } // 組件定義 // 渲染一個(gè)組件 ReactDOM.render( React.createElement(Table, { rows: rows }), // "創(chuàng)建" 一個(gè) component document.getElementById('#root') // 將它放入DOM中 );
當(dāng)ReactDOM.render
被調(diào)用時(shí),React.createElement
最終也會(huì)被調(diào)用,它返回以下對(duì)象:
// 這個(gè)對(duì)象里還有很多其他的字段,但現(xiàn)在對(duì)開(kāi)發(fā)者來(lái)說(shuō)重要的是這些。 { type: Table, props: { rows: rows }, // ... }
這些對(duì)象構(gòu)成了React意義上的Virtual DOM
它們將在所有進(jìn)一步渲染中相互比較,并最終轉(zhuǎn)換為真正的DOM(與Virtual DOM對(duì)比)。
這是另一個(gè)例子:這次有一個(gè)div具有class屬性和幾個(gè)子節(jié)點(diǎn):
React.createElement( 'div', { className: 'cn' }, 'Content 1!', 'Content 2!', );
變成:
{ type: 'div', props: { className: 'cn', children: [ 'Content 1!', 'Content 2!' ] } }
所有的傳入的展開(kāi)函數(shù),也就是React.createElement
除了第一第二個(gè)參數(shù)剩下的參數(shù)都會(huì)在props
對(duì)象中的children
屬性中,不管傳入的是什么函數(shù),他們最終都會(huì)作為children
傳入props
中。
而且,開(kāi)發(fā)者可以直接在JSX代碼中添加children
屬性,將子項(xiàng)直接放在children
中,結(jié)果仍然是相同的:
<div className='cn' children={['Content 1!', 'Content 2!']} />
在Virtual DOM對(duì)象被建立出來(lái)之后ReactDOM.render
會(huì)嘗試按以下規(guī)則把它翻譯成瀏覽器能夠看得懂的DOM節(jié)點(diǎn): -如果
Virtual DOM對(duì)象中的type屬性是一個(gè)string類型的tag名稱,就
創(chuàng)建一個(gè)tag,包含props里的全部屬性。 -如果
Virtual DOM對(duì)象中的type屬性是一個(gè)函數(shù)或者class,就
調(diào)用它,它返回的可能還是一個(gè)Virtual DOM然后將結(jié)果繼續(xù)遞歸調(diào)用此過(guò)程。 -如果
props中有children屬性,就
對(duì)children中的每個(gè)元素進(jìn)行以上過(guò)程,并將返回的結(jié)果放到父DOM節(jié)點(diǎn)中。
最后,瀏覽器獲得了以下HTML(對(duì)于上述table的例子):
<table> <tr> <td>Title</td> </tr> ... </table>
重建DOM
接下瀏覽器要“重建”一個(gè)DOM節(jié)點(diǎn),如果瀏覽器要更新一個(gè)頁(yè)面,顯然,開(kāi)發(fā)者并不希望替換頁(yè)面中的全部元素,這就是React真正的魔法了。如何才能實(shí)現(xiàn)它?先從最簡(jiǎn)單的方法開(kāi)始,重新調(diào)用這個(gè)節(jié)點(diǎn)的ReactDOM.render
方法。
// 第二次調(diào)用 ReactDOM.render( React.createElement(Table, { rows: rows }), document.getElementById('#root') );
這一次,上面的代碼執(zhí)行邏輯將與看到的代碼不同。React不是從頭開(kāi)始創(chuàng)建所有DOM節(jié)點(diǎn)并將它們放在頁(yè)面上,React將使用“diff”算法,以確定節(jié)點(diǎn)樹(shù)的哪些部分必須更新,哪些部分可以保持不變。
那么它是怎樣工作的?只有少數(shù)幾個(gè)簡(jiǎn)單的情況,理解它們將對(duì)React程序的優(yōu)化有很大幫助。請(qǐng)記住,接下來(lái)看到的對(duì)象是用作表示React Virtual DOM中節(jié)點(diǎn)的對(duì)象。
▌Case 1:type是一個(gè)字符串,type在調(diào)用之間保持不變,props也沒(méi)有改變。
// before update { type: 'div', props: { className: 'cn' } } // after update { type: 'div', props: { className: 'cn' } }
這是最簡(jiǎn)單的情況:DOM保持不變。
▌Case 2:type仍然是相同的字符串,props是不同的。
// before update: { type: 'div', props: { className: 'cn' } } // after update: { type: 'div', props: { className: 'cnn' } }
由于type仍然代表一個(gè)HTML元素,React知道如何通過(guò)標(biāo)準(zhǔn)的DOM API調(diào)用更改其屬性,而無(wú)需從DOM樹(shù)中刪除節(jié)點(diǎn)。
▌Case 3:type已更改為不同的組件String或從String組件更改為組件。
// before update: { type: 'div', props: { className: 'cn' } } // after update: { type: 'span', props: { className: 'cn' } }
由于React現(xiàn)在看到類型不同,它甚至不會(huì)嘗試更新DOM節(jié)點(diǎn):舊元素將與其所有子節(jié)點(diǎn)一起被刪除(unmount)。因此,在DOM樹(shù)上替換完全不同的元素的代價(jià)會(huì)非常之高。幸運(yùn)的是,這在實(shí)際情況中很少發(fā)生。
重要的是要記住React使用===(三等)來(lái)比較type值,因此它們必須是同一個(gè)類或相同函數(shù)的相同實(shí)例。
下一個(gè)場(chǎng)景更有趣,因?yàn)檫@是開(kāi)發(fā)者最常使用React的方式。
▌Case 4:type是一個(gè)組件。
// before update: { type: Table, props: { rows: rows } } // after update: { type: Table, props: { rows: rows } }
你可能會(huì)說(shuō),“這好像沒(méi)有任何變化”,但這是不對(duì)的。
如果type是對(duì)函數(shù)或類的引用(即常規(guī)React組件),并且啟動(dòng)了樹(shù)diff比較過(guò)程,那么React將始終嘗試查看組件內(nèi)部的所有child
以確保render
的返回值沒(méi)有更改。即在樹(shù)下比較每個(gè)組件 - 是的,復(fù)雜的渲染也可能變得昂貴!
組件中的children
除了上面描述的四種常見(jiàn)場(chǎng)景之外,當(dāng)元素有多個(gè)子元素時(shí),開(kāi)發(fā)者還需要考慮React的行為。假設(shè)有這樣一個(gè)元素:
// ... props: { children: [ { type: 'div' }, { type: 'span' }, { type: 'br' } ] }, // ...
開(kāi)發(fā)者開(kāi)發(fā)者想將它重新渲染成這樣(span
和div
交換了位置):
// ... props: { children: [ { type: 'span' }, { type: 'div' }, { type: 'br' } ] }, // ...
那么會(huì)發(fā)生什么?
當(dāng)React看到里面的任何數(shù)組類型的props.children
,它會(huì)開(kāi)始將它中的元素與之前看到的數(shù)組中的元素按順序進(jìn)行比較:index 0將與index 0,index 1與index 1進(jìn)行比較,對(duì)于每對(duì)子元素,React將應(yīng)用上述規(guī)則集進(jìn)行比較更新。在以上的例子中,它看到div
變成一個(gè)span
這是一個(gè)情景3中的情況。但這有一個(gè)問(wèn)題:假設(shè)開(kāi)發(fā)者想要從1000行表中刪除第一行。React必須“更新”剩余的999個(gè)孩子,因?yàn)槿绻c先前的逐個(gè)索引表示相比,他們的內(nèi)容現(xiàn)在將不相等。
幸運(yùn)的是,React有一種內(nèi)置的方法來(lái)解決這個(gè)問(wèn)題。如果元素具有key
屬性,則元素將通過(guò)key
而不是索引進(jìn)行比較。只要key
是唯一的,React就會(huì)移動(dòng)元素而不將它們從DOM樹(shù)中移除,然后將它們放回(React中稱為掛載/卸載的過(guò)程)。
// ... props: { children: [ // 現(xiàn)在react就是根據(jù)key,而不是索引來(lái)比較了 { type: 'div', key: 'div' }, { type: 'span', key: 'span' }, { type: 'br', key: 'bt' } ] }, // ...
當(dāng)狀態(tài)改變時(shí)
到目前為止,本文只觸及了props
,React哲學(xué)的一部分,但忽略了state
。這是一個(gè)簡(jiǎn)單的“有狀態(tài)”組件:
class App extends Component { state = { counter: 0 } increment = () => this.setState({ counter: this.state.counter + 1, }) render = () => (<button onClick={this.increment}> {'Counter: ' + this.state.counter} </button>) }
現(xiàn)在,上述例子中的state
對(duì)象有一個(gè)counter
屬性。單擊按鈕會(huì)增加其值并更改按鈕文本。但是當(dāng)用戶點(diǎn)擊時(shí),DOM會(huì)發(fā)生什么?它的哪一部分將被重新計(jì)算和更新?
調(diào)用this.setState
也會(huì)導(dǎo)致重新渲染,但不會(huì)導(dǎo)致整個(gè)頁(yè)面重渲染,而只會(huì)導(dǎo)致組件本身及其子項(xiàng)。父母和兄弟姐妹都可以幸免于難。
修復(fù)問(wèn)題
本文準(zhǔn)備了一個(gè)DEMO,這是修復(fù)問(wèn)題前的樣子。你可以在這里查看其源代碼。不過(guò)在此之前,你還需要安裝React Developer Tools。
打開(kāi)demo要看的第一件事是哪些元素以及何時(shí)導(dǎo)致Virtual DOM更新。導(dǎo)航到瀏覽器的Dev Tools中的React面板,點(diǎn)擊設(shè)置然后選擇“Highlight Updates”復(fù)選框:
現(xiàn)在嘗試在表中添加一行。如你所見(jiàn),頁(yè)面上的每個(gè)元素周圍都會(huì)出現(xiàn)邊框。這意味著每次添加行時(shí),React都會(huì)計(jì)算并比較整個(gè)Virtual DOM樹(shù)?,F(xiàn)在嘗試按一行內(nèi)的計(jì)數(shù)器按鈕。你將看到Virtual DOM如何更新 (state僅相關(guān)元素及其子元素更新)。
React DevTools暗示了問(wèn)題可能出現(xiàn)的地方,但沒(méi)有告訴開(kāi)發(fā)者任何細(xì)節(jié):特別是有問(wèn)題的更新是指元素“diff”之后有不同,還是組件被unmount/mount了。要了解更多信息,開(kāi)發(fā)者需要使用React的內(nèi)置分析器(請(qǐng)注意,它不能在生產(chǎn)模式下工作)。
轉(zhuǎn)到Chrome DevTools中的“Performance”標(biāo)簽。點(diǎn)擊record按鈕,然后點(diǎn)擊表格。添加一些行,更改一些計(jì)數(shù)器,然后點(diǎn)擊“Stop”按鈕。稍等一會(huì)兒之后開(kāi)發(fā)者會(huì)看到:
在結(jié)果輸出中,開(kāi)發(fā)者需要關(guān)注“Timing”??s放時(shí)間軸,直到看到“React Tree Reconciliation”組及其子項(xiàng)。這些都是組件的名稱,旁邊有[update]或[mount]。可以看到有一個(gè)TableRow被mount了,其他所有的TableRow都在update,這并不是開(kāi)發(fā)者想要的。
大多數(shù)性能問(wèn)題都由[update]或[mount]引起
一個(gè)組件(以及組件下的所有東西)由于某種原因在每次更新時(shí)重新掛載,開(kāi)發(fā)者不想讓它發(fā)生(重新掛載很慢),或者在大型分支上執(zhí)行代價(jià)過(guò)大的重繪,即使組件似乎沒(méi)有發(fā)生任何改變。
修復(fù)mount/unmount
現(xiàn)在,當(dāng)開(kāi)發(fā)者了解React如何決定更新Virtual DOM并知道幕后發(fā)生的事情時(shí),終于準(zhǔn)備好解決問(wèn)題了!修復(fù)性能問(wèn)題首先要解決 mount/unmount。
如果開(kāi)發(fā)者將任何元素/組件的多個(gè)子元素在內(nèi)部表示為數(shù)組,那么程序可以獲得非常明顯的速度提升。
考慮一下:
<div> <Message /> <Table /> <Footer /> </div>
在虛擬DOM中,將表示為:
// ... props: { children: [ { type: Message }, { type: Table }, { type: Footer } ] } // ...
一個(gè)簡(jiǎn)單的Message
組件(是一個(gè)div
帶有一些文本,像是豬齒魚(yú)的頂部通知)和一個(gè)很長(zhǎng)的Table
,比方說(shuō)1000多行。它們都是div
元素的child
,因此它們被放置在父節(jié)點(diǎn)的props.children
之下,并且它們沒(méi)有key
。React甚至不會(huì)通過(guò)控制臺(tái)警告來(lái)提醒開(kāi)發(fā)者分配key,因?yàn)樽庸?jié)點(diǎn)React.createElement
作為參數(shù)列表而不是數(shù)組傳遞給父節(jié)點(diǎn)。
現(xiàn)在,用戶已經(jīng)關(guān)閉了頂部通知,所以Message
從樹(shù)中刪除。Table
、Footer
是剩下的child。
// ... props: { children: [ { type: Table }, { type: Footer } ] } // ...
React如何看待它?它將它視為一系列改變了type的child:children[0]的type本來(lái)是Message
,但現(xiàn)在他是Table
。因?yàn)樗鼈兌际菍?duì)函數(shù)(和不同函數(shù))的引用,它會(huì)卸載整個(gè)Table并再次安裝它,渲染它的所有子代:1000多行!
因此,你可以添加唯一鍵(但在這種特殊情況下使用key
不是最佳選擇)或者采用更智能的trick:使用 && 的布爾短路運(yùn)算,這是JavaScript
和許多其他現(xiàn)代語(yǔ)言的一個(gè)特性。像這樣:
<div> {isShowMessage && <Message />} <Table /> <Footer /> </div>
即使Message
被關(guān)閉了(不再顯示),props.children
父母div仍將擁有三個(gè)元素,children[0]具有一個(gè)值false
(布爾類型)。還記得true
/false
,null
甚至undefined
都是Virtual DOM對(duì)象type屬性的允許值嗎?瀏覽器最終得到類似這樣的東西:
// ... props: { children: [ false, // isShowMessage && <Message /> 短路成了false { type: Table }, { type: Footer } ] } // ...
所以,不管Message
是否被顯示,索引都不會(huì)改變,Table
仍然會(huì)和Table
比較,但僅僅比較Virtual DOM通常比刪除DOM節(jié)點(diǎn)并從中創(chuàng)建它們要快得多。
現(xiàn)在來(lái)看看更高級(jí)的東西。開(kāi)發(fā)者喜歡HOC。高階組件是一個(gè)函數(shù),它將一個(gè)組件作為一個(gè)參數(shù),添加一些行為,并返回一個(gè)不同的組件(函數(shù)):
function withName(SomeComponent) { return function(props) { return <SomeComponent {...props} name={name} />; } }
開(kāi)發(fā)者在父render
方法中創(chuàng)建了一個(gè)HOC 。當(dāng)React
需要重新渲染樹(shù)時(shí),React
的Virtual DOM將如下所示:
// On first render: { type: ComponentWithName, props: {}, } // On second render: { type: ComponentWithName, // Same name, but different instance props: {}, }
現(xiàn)在,React只會(huì)在ComponentWithName上運(yùn)行一個(gè)diff算法,但是這次同名引用了一個(gè)不同的實(shí)例,三等于比較失敗,必須進(jìn)行完全重新掛載。注意它也會(huì)導(dǎo)致?tīng)顟B(tài)丟失,幸運(yùn)的是,它很容易修復(fù):只要返回的實(shí)例都是同一個(gè)就好了:
// 單例 const ComponentWithName = withName(Component); class App extends React.Component() { render() { return <ComponentWithName />; } }
修復(fù)update
現(xiàn)在瀏覽器已經(jīng)確保不會(huì)重新裝載東西了,除非必要。但是,對(duì)位于DOM樹(shù)根目錄附近的組件所做的任何更改都將導(dǎo)致其所有子項(xiàng)的進(jìn)行對(duì)比重繪。結(jié)構(gòu)復(fù)雜,價(jià)格昂貴且經(jīng)常可以避免。
如果有辦法告訴React不要查看某個(gè)分支,那將是很好的,因?yàn)樗鼪](méi)有任何變化。
這種方式存在,它涉及一個(gè)叫shouldComponentUpdate
的組件生命周期函數(shù)。React會(huì)在每次調(diào)用組件之前調(diào)用此方法,并接收props
和state
的新值。然后開(kāi)發(fā)者可以自由地比較新值和舊值之間的區(qū)別,并決定是否應(yīng)該更新組件(返回true
或false
)。如果函數(shù)返回false
,React將不會(huì)重新渲染有問(wèn)題的組件,也不會(huì)查看其子組件。
通常比較兩組props
和state
一個(gè)簡(jiǎn)單的淺層比較就足夠了:如果頂層屬性的值相同,瀏覽器就不必更新了。淺比較不是JavaScript
的一個(gè)特性,但開(kāi)發(fā)者很多方法來(lái)自己實(shí)現(xiàn)它,為了不重復(fù)造輪子,也可以使用別人寫(xiě)好的方法。
在引入淺層比較的npm包后,開(kāi)發(fā)者可以編寫(xiě)如下代碼:
class TableRow extends React.Component { shouldComponentUpdate(nextProps, nextState) { const { props, state } = this; return !shallowequal(props, nextProps) && !shallowequal(state, nextState); } render() { /* ... */ } }
但是你甚至不必自己編寫(xiě)代碼,因?yàn)镽eact在一個(gè)名為React.PureComponent的類中內(nèi)置了這個(gè)功能,它類似于React.Component
,只是shouldComponentUpdate
已經(jīng)為你實(shí)現(xiàn)了淺層props/state比較。
或許你會(huì)有這樣的想法,能替換Component
為PureComponent
就去替換。但開(kāi)發(fā)者如果錯(cuò)誤地使用PureComponent
同樣會(huì)有重新渲染的問(wèn)題存在,需要考慮下面三種情況:
<Table // map每次都會(huì)返回一個(gè)新的數(shù)組實(shí)例,所以每次比較都是不同的 rows={rows.map(/* ... */)} // 每一次傳入的對(duì)象都是新的對(duì)象,引用是不同的。 style={ { color: 'red' } } // 箭頭函數(shù)也一樣,每次都是不同的引用。 onUpdate={() => { /* ... */ }} />
上面的代碼片段演示了三種最常見(jiàn)的反模式,請(qǐng)盡量避免它們!
正確地使用PureComponent
,你可以在這里看到所有的TableRow都被“純化”后渲染的效果。
但是,如果你迫不及待想要全部使用純函數(shù)組件,這樣是不對(duì)的。比較兩組props
和state
不是免費(fèi)的,對(duì)于大多數(shù)基本組件來(lái)說(shuō)甚至都不值得:運(yùn)行shallowCompare
比diff算法需要更多時(shí)間。
可以使用此經(jīng)驗(yàn)法則:純組件適用于復(fù)雜的表單和表格,但它們通常會(huì)使按鈕或圖標(biāo)等簡(jiǎn)單元素變慢。
現(xiàn)在,你已經(jīng)熟悉了React的渲染模式,接下來(lái)就開(kāi)始前端優(yōu)化之旅吧。
到此這篇關(guān)于React 的 Virtual DOM的文章就介紹到這了,更多相關(guān)React 的 Virtual DOM內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql 數(shù)據(jù)庫(kù)中索引原理分析說(shuō)明
實(shí)際上,您可以把索引理解為一種特殊的目錄。微軟的SQLSERVER提供了兩種索引:聚集索引(clustered index,也稱聚類索引、簇集索引)和非聚集索引(nonclustered index,也稱非聚類索引、非簇集索引)。2010-03-03遠(yuǎn)程連接局域網(wǎng)內(nèi)的sql server 無(wú)法連接 錯(cuò)誤與解決方法
下面我們依次介紹如何來(lái)解決這三個(gè)最常見(jiàn)的連接錯(cuò)誤。2009-09-09如何恢復(fù)數(shù)據(jù)庫(kù)備份到一個(gè)已存在的正在使用的數(shù)據(jù)庫(kù)上
如何恢復(fù)數(shù)據(jù)庫(kù)備份到一個(gè)已存在的正在使用的數(shù)據(jù)庫(kù)上...2007-01-01SQL?Server還原完整備份和差異備份的操作過(guò)程
這篇文章主要介紹了SQL?Server?還原?完整備份和差異備份的詳細(xì)操作,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09SQL SERVER 2014 安裝圖解教程(含SQL SERVER 2014下載)
這篇文章主要介紹了SQL SERVER 2014 安裝圖解教程(含SQL SERVER 2014下載),需要的朋友可以參考下2015-10-10sqlserver 自動(dòng)備份所有數(shù)據(jù)庫(kù)的SQL
可自動(dòng)備份除系統(tǒng)數(shù)據(jù)庫(kù)外的所有數(shù)據(jù)庫(kù)。備份文件的周期保存周期可以更改。2010-03-03SQLServer中字符串左對(duì)齊或右對(duì)齊顯示的sql語(yǔ)句
在顯示數(shù)據(jù)時(shí)需要對(duì)數(shù)據(jù)進(jìn)行美觀化顯示。如左對(duì)齊,右對(duì)齊2012-05-05SQL Server簡(jiǎn)單模式下誤刪除堆表記錄恢復(fù)方法(繞過(guò)頁(yè)眉校驗(yàn))
這篇主旨是揭示堆表的刪除記錄找回的原理,我所考慮的方面并不適用于每個(gè)人的每種情況,望大家見(jiàn)諒2013-01-01淺析SQL Server 聚焦索引對(duì)非聚集索引的影響
本篇文章對(duì)SQL Server的聚焦索引和非聚集索引進(jìn)行簡(jiǎn)單分析,從而總結(jié)出聚焦索引對(duì)非聚集索引的影響。有興趣的朋友可以看下2016-12-12