當前位置:首頁 » 編程軟體 » 預編譯節點

預編譯節點

發布時間: 2022-09-21 11:51:27

❶ vc++6.0編譯時出現錯誤,如何調整工具欄目錄路徑

致命錯誤 C1010
在查找預編譯頭時遇到意外的文件結尾。是否忘記了向源代碼中添加「#include name」?
用 /Yu 指定的包含文件沒有列在源文件中。在大多數的 Visual C++ 項目類型中,此選項默認是啟用的,而且「stdafx.h」是此選項指定的默認包含文件。
在 Visual Studio 環境中,請使用下列方法之一消除此錯誤:
如果項目中沒有使用預編譯頭,請將源文件的「創建/使用預編譯頭」屬性設置為「不使用預編譯頭」。若要設置此編譯器選項,請遵循以下這些步驟:
在項目的「解決方案資源管理器」窗格中,右擊項目名稱,再單擊「屬性」。
在左窗格中單擊「C/C++」文件夾
單擊「預編譯頭」節點。
在右窗格中單擊「創建/使用預編譯頭」,再單擊「不使用預編譯頭」。
確保您沒有在不注意的情況下從當前項目中刪除、重命名或移除頭文件(默認為 stdafx.h)。還需要使用 #include "stdafx.h" 在源文件中的任何其他代碼之前包含這一文件。(此頭文件被指定為「通過文件創建/使用 PCH」項目屬性)
http://msdn.microsoft.com/zh-cn/library/d7fz9ckx.aspx

❷ Web前端工程師該如何選擇web前端模板引擎

今天小編要跟大家分享的文章是關於Web前端工程師該如何選擇web前端模板引擎?如果你正在從事web前端工作,如果你也想要了解如何選擇web前端模板引擎的知識,那麼就來和小編一起看一看本文為大家介紹的內容吧~


一、Web模板就在那裡


模板引擎負責組裝數據,以另外一種形式或外觀展現數據。瀏覽器中的頁面是Web模板引擎最終的展現。


無論你是否直接使用模板引擎,Web模板一直都在,不在前端就在後端,它的出現甚至可以追溯到超文本標記語言HTML標准正式確立之前。


二、服務端的模板引擎


我所知道最早的Web模板引擎是PHP,它正式誕生於1997年,工作在伺服器端。讓我們看看PHP官方的intro-whatis:


PHP(「PHP:Hypertext
Preprocessor」,超文本預處理器的縮寫)是一種被廣泛應用的開放源代碼的多用途腳本語言,它可嵌入到HTML中,尤其適合web開發。


PHPer普遍贊同PHP本身就是最天然、原生的PHP模板引擎,因為她本來就是。在PHP的世界裡多次出現過再包裝的模板引擎,著名的有
smarty。


其它伺服器端語言很多都有HTML模板引擎,比如JSP、mustache。


毫無疑問,這些伺服器端模板引擎最終生成的結果是HTML(XML)字元串,處理流程邏輯使用宿主語言本身的語法實現。


它們的共同特徵:HTML只是個字元串,最終結果可能還需要類似Tidy這樣的清潔或修正驗證工具。


這里提出一個問題:二次封裝的smarty有存在的必要麼?


三、瀏覽器端的模板引擎


我所知道最早的前端模板引擎是jCT,它託管於Google
Code,誕生於2008年,宿主語言是javaScript,工作在瀏覽器中。很榮幸,我就是jCT的作者,相關早期博客可以查看achun、githubjCT
備份。


直到今天寫這篇文章,我才發現pure-js這篇文章裡面也提到不少先行者——jemplate最早在2006年就創建了。


今天在OSC搜索JavaScript模板引擎你會得到100+個結果,下邊列舉一些:


·輕量度:tpl.js、T.js


·認知度:arttemplate、mustache.js、doT.js、handlebars.js、pug


·DOM-tree-based:domTemplate、transparency、plates


·VDOM-based:htmltemplate-vdom、virtual-stache、html-patcher


·流行框架:Vue.js、ReactJS、riot


·Real-DOM:PowJS


它們的共同特徵:全都支持插值。


這里還有templating-engines受歡迎度的對比,甚至best-javascript-templating-engines
投票及正反方的理由。


四、如何選擇


我認為存在即合理,每個引擎、框架總有可取之處,至少在你的應用里,在某個時代,所以本文不會評論某個引擎哪一點不好,那樣是不客觀的。現在回答前邊提到的問題:smarty
有存在的必要麼?我的答案是:有。理由很簡單,看給誰用、看大背景。


對於前後端沒有分離的應用,或前端人員對後端語言不夠熟悉,或因崗位職責需要,那麼前端人員掌握一種比較通用的模板語法(語言)是現實的,反之讓PHPer自己去使用
smarty那就太浪費技能了。


下面是通常意義上的引擎選擇建議:


1.前提,選擇的引擎能滿足數據渲染需求,且不和現有依賴沖突,如果你已經非常熟悉某個引擎,那你已經有答案了。


2.是一次性的項目需求么?是的話直接選擇輕量的,學習復雜度最低的。


3.是要做組件開發么?


4.引擎支持預編譯結果,不必每次都實時編譯么?


5.要跨平台么?有官方提供支持的,首選類React-JSX的引擎或純粹的VDOM引擎。


6.選擇學習或維護復雜度最低的,眾所周知,開發者對調試的時間超過寫代碼的時間深惡痛絕。


7.最後才是性能對比,性能對比是一件非常細致的工作,他人的對比結果不一定符合你的場景。


我認為應該弱化語法風格的對比,偏好是沒有可比性的,一些語法甚至有特殊的背景原因。


為什麼最後才是性能對比?


性能的確很重要,但如果性能還沒有影響到你的應用體驗度,那就忽視它。很難真實地模擬應用場景,通常只有通過真實場景來檢驗,目前的測試工具還達不到這種效果。


前述問題有些有固定答案,下面討論餘下的問題:如何考慮組件開發、支持預編譯、復雜度?


五、組件開發


進行組件開發已經不再是選擇模板引擎的問題了,這是生態環境選擇的問題。如果你的應用需要更快地完成,那麼時間點是第一位的,就選擇流行框架,有足夠多的組件讓你使用或參考。如果你的應用有獨立的生態環境,需要技術選型以便長期維護,那繼續看下文。


六、預編譯


預編譯應該具備:


1.編譯結果在目標環境中不再需要編譯過程。


2.編譯結果可調試性,這意味著結果應該包含原生ECMAScript代碼,而不是純粹的數據描述。


大家都知道React-JSX是支持預編譯的,官方的說法是ReactWithoutJSX,即總是build過的。


一些基於字元串處理的引擎也支持預編譯。如果你需要預編譯,建議拋棄編譯結果依然是基於字元串拼接的引擎,那樣還不如不預編譯,那是HTML5未被廣泛支持之前的技術手段。


至少也要有類似React-JSX這樣的編譯結果才具有可調試性。備註:Vue.js支持多種模板引擎,可達到同樣的效果。


原ReactJS代碼,其中用到了WebComponents技術:classHelloMessageextendsReact.Component{

render(){

return

Hello{this.props.name}!

❸ android系統為什麼歷史任務裡面總有信息任務

若是要回答這個問題,我們需要追溯到上個世紀,去尋找智能手機的起源。
1965 年,貝爾實驗室、通用電氣和麻省理工學院開始合作開發一套能夠兼顧易用性和強大性的操作系統,經過六年時間的通力協作,貝爾實驗室的一名軟體工程師 Ken Thompson 在休假期間完成了一個名為 Unix 的系統編寫,並最終成為貝爾實驗室的母公司、美國電信巨頭 AT&T的商業產品,並啟動了長達數十年的版權運作。盡管後來有著許多變種,但是從嚴格意義上來講,Unix 不是一個開源的操作系統。
1991 年,一個芬蘭的大學生、同時也是計算機黑客的 Linus Torvalds,他對 Unix 十分著迷,但是買不起運行 Unix 需要的工作站,所以他就嘗試自己以同樣的編程方式寫了一個名為 linux 的操作系統,並在自由軟體之父 Richard Stallman 的精神鼓舞之下,將 Linux 加入到了自由軟體基金(FSF)當中,允許所有人使用、拷貝、修改甚至銷售 Linux 系統,同時承擔開源義務,禁止把 Linux 封閉化的企圖。
之所以要如此大費周章的講述 Unix 和 Linux 兩個操作系統的故事,是因為 iOS 和 Android,正是分別基於 Unix 和 Linux 而衍生出來的作品。也就是說,是 Unix 和 Linux 的兩種特性,造成了 iPhone 與 Android 手機在使用體驗上的巨大差異。
喬布斯曾經邀請 Linux 的創始者 Linus Torvalds 到蘋果工作,放棄 Linux 的開源,協助開發 Mac OS 封閉式的 Mach 內核,後者與喬布斯大吵一架之後明確表示拒絕。而從 Mac OS 開始,蘋果就將操作系統的私有化視為企業戰略,用喬布斯的話來講,他是將 iOS 裝進了 iPhone 這個盒子里,然後賣給了用戶。所以,iPhone 之所以不會出現「越用越卡」的情況,是因為蘋果公司對它的手機從硬體到軟體擁有最高的管理許可權,在封閉式的環境中,來自第三方的應用程序無法調用超過 iPhone 承受限度的指令,自然也不可能造成持續性的系統損傷。
反觀 Android 手機,由於開源的公開條件,Google 無法從代碼這一埠約束第三方的應用程序,同時,由於 Linux 核心設定應用在調取系統功能時一定要取得 ROOT 許可權,這也導致大量應用因為單一功能的實現需求而獲得整個 ROOT 層面的支配,可以在 Android 手機的任意儲存位置進行讀寫,這種高自由度無異於開啟了潘多拉魔盒,讓 Android 手機無法對惡意 App 事先設防。這也是開源軟體備受爭議、且在商用領域遭到抵觸的原因:它只關心是否授予了用戶自由——這個自由也包括逾越邊界的自由——而沒有從最壞的出發點去考慮如何規避被濫用的風險。盡管 Google 作為巨頭,一直在嘗試對產業鏈進行統一管理,但是當這條產業鏈日益龐大、連 Google 也只能扮演其中之一的角色時,Android 的失控也就在情理之中了。比如,Android 的最新版本通常需要花費超過一年半的時間,才能使激活它的 Android 手機佔比超過 50%,但是 iOS 7 只用了兩個月,就讓半數以上的 iPhone 都更新完畢。另外,一款應用程序如果被蘋果從 App Store 中懲罰出去,它就再也無法被安裝到任何一款合法的 iPhone 裡面,但是如果一款應用程序被 Google 驅逐出 Google Play,但是它還是可以登錄各種第三方應用市場,提供正常的下載和安裝。
所以,Android 的這種天生短板,又催生出了一個「手機調校」的市場,並帶動了新的產業鏈。
「手機調校」的第一級,在於系統層。在 Android 4.4 以及之後的 Android L 的規劃中,它將應用程序的運行模式由 Dalvik 換成了 ART,其原理簡單來說是「預編譯」效果,即當一款應用程序在第一次被安裝到 Android 時,它的位元組碼就已經被編譯成為了本地的機器碼,減少後續運行應用程序時的啟動和執行時間。
根據 Google 自己公布的結果,在不同的性能測試 App 中,ART 的速度對比 Dalvik 的平均提升幅度達到了 80%,在某些項目中,ART 的提升幅度甚至超過了 1.5 倍,這個結果可謂非常喜人。
這是 Google 希望從源頭解決 Android 卡慢問題的努力,但是這只是對性能優化有著作用,無法解決因為應用程序違規調用資源而產生的問題。同時,由於在安裝應用程序時進行了「預編譯」,整個安裝時間將會變長,安裝完畢後生成的文件也會變大,比如最新的 Google+ 安裝包只有 6.9M,但是它安裝後的 APK 大小達到了 28.3M,這對 Android 手機儲存空間又存在過多佔用的問題。
「手機調校」的第二級,在於 ROM 層。作為全球最大的 Android 市場,中國的許多手機廠商都以開發專用 ROM 來為銷售產品添彩,大多數的 ROM,也都會考慮對 Android 系統進行優化,比如 MIUI V6 就宣稱「引入多種 Linux 系統內核內存優化技術,提高應用運行效率」。
也就是說,與 Google 做的事情一樣,ROM 廠商主要的優化工作,也是對 Linux 動刀,打上各種補丁,使其底層語言能夠更好的適配到各種手機終端上。還是以 MIUI V6 為例,在介紹新特性時,其有這么一條:「ZRAM 調度優化技術」,其實 ZARM 就是 Linux 內核里的一個內存模塊,作用就是在內存中劃出一個部分出來充當虛擬盤,來承載 Linux 的交換分區,將一些任務壓縮容納進去,使內存的使用率提高,讓 CPU 來為內存服務(因為目前的智能手機普遍 CPU 過剩、而內存才是瓶頸)。
不過,ROM 也是一把雙刃劍,它對於 Android 底層系統的修改,以及它對於內存空間的佔用,又都有增加手機負載的風險。
「手機調校」的第三級,在於應用層。大量應用程序在手機中發生的意外或故意佔用事件,是造成 Android 手機越來越慢的最核心原因。過多的應用程序熱衷於滯留在內存空間里、以及將大量碎片留在儲存空間里,是帶來麻煩的罪魁禍首。這也是為什麼即時清理類應用得以逐漸成為 Android 手機標配。
Android 系統有七類進程,分別是前台進程、可見進程、主要服務、次要服務、後台進程、內容供應節點、空進程,在沒有安裝清理類應用的時候,一部 Android 手機只能依賴系統默認的分配機制來自動調節內存使用,只要應用程序提出請求,大部分進程只要打開後都會被保留在內存當中,這原本是為了讓用戶在再度激活這些進程時不需要重新載入、節省時間的初衷考慮,但是 Android 沒有料到激烈的市場競爭會驅使應用程序產生「劣幣驅良幣」的趨勢,很多開發者出於商業目的,在不需要留存在內存的情況下也想方設法的讓應用程序保持潛在運行狀態,一個兩個還好說,但是一旦數量更多,Anrdoid 手機就會頻頻卡頓和發熱。
以目前全球用戶規模最大的 Android 手機清理類應用「某清理大師」為例,它清理的進程類型,主要放在後台進程、次要服務、內容供應節點和空進程:
後台進程(Hidden)——這個是最優先被掃描和識別出來的進程,因為大部分 Android 用戶在切換應用程序時都不會使用返回鍵退出,而是直接按下 Home 鍵,前者會讓應用進入空進程(佔用資源相對較小),而後者則會保留為後台進程(佔用資源相對更大),尤其是當游戲類 App 在後台運行時,它會和其他 App 爭搶資源,而不會在乎那款 App 是不是用戶正在使用。根據某清理大師的統計,約有 20% 的常用 App 即使不運行時也在後台啟動聯網,主要是提交產品及用戶使用信息、獲取廣告信息、查詢是否升級等。
次要服務(Secondary Server)——比如某些企業套件、郵箱聯系人、觸控介面等,這些進程很多都是系統自帶的,有些用戶會使用,但是有些用戶也可能不會使用或已經有了替代應用,所以某清理大師的清理邏輯是基於用戶行為和授權來建立(分為建議清理和深度清理兩類);
內容供應節點(Content Provider)——這部分進程沒有程序實體,僅僅提供內容給其他應用使用,比如日歷供應節點、郵件供應節點等,除了佔用內存資源之外,它還會佔用網路,所以也會給 Android 手機造成不必要的負擔;
空進程(Empty)——如果是通過返回鍵退出應用,大部分的應用也會在 Android 手機的內存里遺留一個空的進程,這個進程沒有數據運行,但是會記錄應用的歷史信息,幾乎沒有任何價值,同樣,這部分進程內容被幹掉的優先順序也很高。
除了對內存的過度消耗之外,Android 手機也容易在儲存中積累大量冗餘數據,包括無法卸載的預裝應用、卸載之後的殘存文件以及使用應用的過程中產生的緩存,由於 Android 本身沒有提供管理工具,即使將手機連接電腦之後也是如同 Windows 樹狀結構一樣的文件夾包,用戶很難獨立判斷哪些文件夾可以刪除、哪些文件夾是系統必備的,最後也會導致手機尺寸空間愈來愈窄的情況。
「手機調校」的問題,可能又回帶來用戶操作的負擔增加,其心理壓力甚於行為壓力,玩著手機還不忘隔三差五的使用清理功能,這種與 iPhone 相比「別具特色」的操作習慣,也是 Android 手機永遠像一個半成品或工程機的原因。

❹ pdflib在MFC中的使用

VC環境中和MFC中不是一回事嗎?

錯誤消息
在查找預編譯頭時遇到意外的文件結尾。是否忘記了向源代碼中添加「#include name」?

用 /Yu 指定的包含文件沒有列在源文件中。在大多數的 Visual C++ 項目類型中,此選項默認是啟用的,而且「stdafx.h」是此選項指定的默認包含文件。

在 Visual Studio 環境中,請使用下列方法之一消除此錯誤:

如果項目中沒有使用預編譯頭,請將源文件的「創建/使用預編譯頭」屬性設置為「不使用預編譯頭」。若要設置此編譯器選項,請遵循以下這些步驟:

在項目的「解決方案資源管理器」窗格中,右擊項目名稱,再單擊「屬性」。

在左窗格中單擊「C/C++」文件夾。

單擊「預編譯頭」節點。

在右窗格中單擊「創建/使用預編譯頭」,再單擊「不使用預編譯頭」。

確保您沒有在不注意的情況下從當前項目中刪除、重命名或移除頭文件(默認為 stdafx.h)。還需要使用 #include "stdafx.h" 在源文件中的任何其他代碼之前包含這一文件。(此頭文件被指定為「通過文件創建/使用 PCH」項目屬性)
參考資料:
ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_vccomp/html/dfd035f1-a7a2-40bc-bc92-dc4d7f456767.htm

❺ 簡單的給我介紹下網路協議中的TCP協議的數據結構是怎麼樣的

sk_buff結構可能是linux網路代碼中最重要的數據結構,它表示接收或發送數據包的包頭信息。它在<include/linux/skbuff.h>中定義,並包含很多成員變數供網路代碼中的各子系統使用。這個結構在linux內核的發展過程中改動過很多次,或者是增加新的選項,或者是重新組織已存在的成員變數以使得成員變數的布局更加清晰。它的成員變數可以大致分為以下幾類:Layout 布局General 通用Feature-specific功能相關Management functions管理函數 這個結構被不同的網路層(MAC或者其他二層鏈路協議,三層的IP,四層的TCP或UDP等)使用,並且其中的成員變數在結構從一層向另一層傳遞時改變。L4向L3傳遞前會添加一個L4的頭部,同樣,L3向L2傳遞前,會添加一個L3的頭部。添加頭部比在不同層之間拷貝數據的效率更高。由於在緩沖區的頭部添加數據意味著要修改指向緩沖區的指針,這是個復雜的操作,所以內核提供了一個函數skb_reserve(在後面的章節中描述)來完成這個功能。協議棧中的每一層在往下一層傳遞緩沖區前,第一件事就是調用skb_reserve在緩沖區的頭部給協議頭預留一定的空間。skb_reserve同樣被設備驅動使用來對齊接收到包的包頭。如果緩沖區向上層協議傳遞,舊的協議層的頭部信息就沒什麼用了。例如,L2的頭部只有在網路驅動處理L2的協議時有用,L3是不會關心它的信息的。但是,內核並沒有把L2的頭部從緩沖區中刪除,而是把有效荷載的指針指向L3的頭部,這樣做,可以節省CPU時間。1. 網路參數和內核數據結構 就像你在瀏覽TCP/IP規范或者配置內核時所看到的一樣,網路代碼提供了很多有用的功能,但是這些功能並不是必須的,比如說,防火牆,多播,還有其他一些功能。大部分的功能都需要在內核數據結構中添加自己的成員變數。因此,sk_buff裡麵包含了很多像#ifdef這樣的預編譯指令。例如,在sk_buff結構的最後,你可以找到:struct sk_buff { ... ... ...#ifdef CONFIG_NET_SCHED _ _u32 tc_index;#ifdef CONFIG_NET_CLS_ACT _ _u32 tc_verd; _ _u32 tc_classid;#endif#endif}
它表明,tc_index只有在編譯時定義了CONFIG_NET_SCHED符號才有效。這個符號可以通過選擇特定的編譯選項來定義(例如:"Device Drivers Networking supportNetworking options QoS and/or fair queueing")。這些編譯選項可以由管理員通過make config來選擇,或者通過一些自動安裝工具來選擇。前面的例子有兩個嵌套的選項:CONFIG_NET_CLS_ACT(包分類器)只有在選擇支持「QoS and/or fair queueing」時才能生效。順便提一下,QoS選項不能被編譯成內核模塊。原因就是,內核編譯之後,由某個選項所控制的數據結構是不能動態變化的。一般來說,如果某個選項會修改內核數據結構(比如說,在sk_buff
裡面增加一個項tc_index),那麼,包含這個選項的組件就不能被編譯成內核模塊。你可能經常需要查找是哪個make config編譯選項或者變種定義了某個#ifdef標記,以便理解內核中包含的某段代碼。在2.6內核中,最快的,查找它們之間關聯關系的方法,就是查找分布在內核源代碼樹中的kconfig文件中是否定義了相應的符號(每個目錄都有一個這樣的文件)。在
2.4內核中,你需要查看Documentation/Configure.help文件。2. Layout Fields有些sk_buff成員變數的作用是方便查找或者是連接數據結構本身。內核可以把sk_buff組織成一個雙向鏈表。當然,這個鏈表的結構要比常見的雙向鏈表的結構復雜一點。就像任何一個雙向鏈表一樣,sk_buff中有兩個指針next和prev,其中,next指向下一個節點,而
prev指向上一個節點。但是,這個鏈表還有另一個需求:每個sk_buff結構都必須能夠很快找到鏈表頭節點。為了滿足這個需求,在第一個節點前面會插入另一個結構sk_buff_head,這是一個輔助節點,它的定義如下:struct sk_buff_head { struct sk_buff * next; struct sk_buff * prev; _ _u32 qlen; spinlock_t lock; }; qlen代表鏈表元素的個數。lock用於防止對鏈表的並發訪問。sk_buff和sk_buff_head的前兩個元素是一樣的:next和prev指針。這使得它們可以放到同一個鏈表中,盡管sk_buff_head要比sk_buff小得多。另外,相同的函數可以同樣應用於sk_buff和sk_buff_head。為了使這個數據結構更靈活,每個sk_buff結構都包含一個指向sk_buff_head的指針。這個指針的名字是list。圖1會幫助你理解它們之間的關系。Figure 1. List of sk_buff elements

❻ 致命錯誤:在搜索預編譯頭文件時遇到意外的文件結尾的指令。錯誤在哪兒 啊大神們

4個錯誤
0.NULL不需要你來define
1.printf('delete:%ld\n",num); //左邊用了單引號
2.while(num!p1->num&&p1->next==NULL); //應該是num != p1->num
3.sxanf("%ld",&del_num);/*輸入要刪除的學號*/ // 是scanf
另外
main函數最好聲明為int型,這是標准C對main函數的要求
聲明為void的main函數在標准C編譯器上是通不過編譯的

❼ VUE 響應式原理 和 Virtual DOM

在 Vue 中,數據模型下的所有屬性,會被 Vue 使用 Object.defineProperty (Vue3.0 使用 Proxy)進行數據劫持代理。響應式的核心機制是觀察者模式,數據是被觀察的一方,一旦發生變化,通知所有觀察者,這樣觀察者可以做出響應,比如當觀察者為視圖時,視圖可以做出視圖的更新。

Vue.js 的響應式系統以來三個重要的概念, Observer 、 Dep 、 Watcher 。

Observe 扮演的角色是發布者,他的主要作用是在組件 vm 初始化的時,調用 defineReactive 函數,使用 Object.defineProperty 方法對對象的每一個子屬性進行數據劫持/監聽,即為每個屬性添加 getter 和 setter ,將對應的屬性值變成響應式。

在組件初始化時,調用 initState 函數,內部執行 initState 、 initProps 、 initComputed 方法,分別對 data 、 prop 、 computed 進行初始化,讓其變成響應式。

初始化 props 時,對所有 props 進行遍歷,調用 defineReactive 函數,將每個 prop 屬性值變成響應式,然後將其掛載到 _props 中,然後通過代理,把 vm.xxx 代理到 vm._props.xxx 中。

同理,初始化 data 時,與 prop 相同,對所有 data 進行遍歷,調用 defineReactive 函數,將每個 data 屬性值變成響應式,然後將其掛載到 _data 中,然後通過代理,把 vm.xxx 代理到 vm._data.xxx 中。

初始化 computed ,首先創建一個觀察者對象 computed-watcher ,然後遍歷 computed 的每一個屬性,對每一個屬性值調用 defineComputed 方法,使用 Object.defineProperty 將其變成響應式的同時,將其代理到組件實例上,即可通過 vm.xxx 訪問到 xxx 計算屬性。

Dep 扮演的角色是調度中心/訂閱器,在調用 defineReactive 將屬性值變成響應式的過程中,也為每個屬性值實例化了一個 Dep ,主要作用是對觀察者(Watcher)進行管理,收集觀察者和通知觀察者目標更新,即當屬性值數據發生改變時,會遍歷觀察者列表(dep.subs),通知所有的 watcher,讓訂閱者執行自己的update邏輯。

其 dep 的任務是,在屬性的 getter 方法中,調用 dep.depend() 方法,將觀察者(即 Watcher,可能是組件的render function,可能是 computed,也可能是屬性監聽 watch)保存在內部,完成其依賴收集。在屬性的 setter 方法中,調用 dep.notify() 方法,通知所有觀察者執行更新,完成派發更新。

Watcher 扮演的角色是訂閱者/觀察者,他的主要作用是為觀察屬性提供回調函數以及收集依賴,當被觀察的值發生變化時,會接收到來自調度中心 Dep 的通知,從而觸發回調函數。

而 Watcher 又分為三類, normal-watcher 、 computed-watcher 、 render-watcher 。

這三種 Watcher 也有固定的執行順序,分別是:computed-render -> normal-watcher -> render-watcher。這樣就能盡可能的保證,在更新組件視圖的時候,computed 屬性已經是最新值了,如果 render-watcher 排在 computed-render 前面,就會導致頁面更新的時候 computed 值為舊數據。

Observer 負責將數據進行攔截,Watcher 負責訂閱,觀察數據變化, Dep 負責接收訂閱並通知 Observer 和接收發布並通知所有 Watcher。

在 Vue 中, template 被編譯成瀏覽器可執行的 render function ,然後配合響應式系統,將 render function 掛載在 render-watcher 中,當有數據更改的時候,調度中心 Dep 通知該 render-watcher 執行 render function ,完成視圖的渲染與更新。

整個流程看似通順,但是當執行 render function 時,如果每次都全量刪除並重建 DOM,這對執行性能來說,無疑是一種巨大的損耗,因為我們知道,瀏覽器的DOM很「昂貴」的,當我們頻繁的更新 DOM,會產生一定的性能問題。

為了解決這個問題,Vue 使用 JS 對象將瀏覽器的 DOM 進行的抽象,這個抽象被稱為 Virtual DOM。Virtual DOM 的每個節點被定義為 VNode ,當每次執行 render function 時,Vue 對更新前後的 VNode 進行 Diff 對比,找出盡可能少的我們需要更新的真實 DOM 節點,然後只更新需要更新的節點,從而解決頻繁更新 DOM 產生的性能問題。

VNode,全稱 virtual node ,即虛擬節點,對真實 DOM 節點的虛擬描述,在 Vue 的每一個組件實例中,會掛載一個 $createElement 函數,所有的 VNode 都是由這個函數創建的。

比如創建一個 div:

render 函數執行後,會根據 VNode Tree 將 VNode 映射生成真實 DOM,從而完成視圖的渲染。

Diff 將新老 VNode 節點進行比對,然後將根據兩者的比較結果進行最小單位地修改視圖,而不是將整個視圖根據新的 VNode 重繪,進而達到提升性能的目的。

Vue.js 內部的 diff 被稱為 patch 。其 diff 演算法的是通過同層的樹節點進行比較,而非對樹進行逐層搜索遍歷的方式,所以時間復雜度只有O(n),是一種相當高效的演算法。

首先定義新老節點是否相同判定函數 sameVnode :滿足鍵值 key 和標簽名 tag 必須一致等條件,返回 true ,否則 false 。

在進行 patch 之前,新老 VNode 是否滿足條件 sameVnode(oldVnode, newVnode) ,滿足條件之後,進入流程 patchVnode ,否則被判定為不相同節點,此時會移除老節點,創建新節點。

patchVnode 的主要作用是判定如何對子節點進行更新,

Diff 的核心,對比新老子節點數據,判定如何對子節點進行操作,在對比過程中,由於老的子節點存在對當前真實 DOM 的引用,新的子節點只是一個 VNode 數組,所以在進行遍歷的過程中,若發現需要更新真實 DOM 的地方,則會直接在老的子節點上進行真實 DOM 的操作,等到遍歷結束,新老子節點則已同步結束。

updateChildren 內部定義了4個變數,分別是 oldStartIdx 、 oldEndIdx 、 newStartIdx 、 newEndIdx ,分別表示正在 Diff 對比的新老子節點的左右邊界點索引,在老子節點數組中,索引在 oldStartIdx 與 oldEndIdx 中間的節點,表示老子節點中為被遍歷處理的節點,所以小於 oldStartIdx 或大於 oldEndIdx 的表示未被遍歷處理的節點。同理,在新的子節點數組中,索引在 newStartIdx 與 newEndIdx 中間的節點,表示老子節點中為被遍歷處理的節點,所以小於 newStartIdx 或大於 newEndIdx 的表示未被遍歷處理的節點。

每一次遍歷, oldStartIdx 和 oldEndIdx 與 newStartIdx 和 newEndIdx 之間的距離會向中間靠攏。當 oldStartIdx > oldEndIdx 或者 newStartIdx > newEndIdx 時結束循環。

在遍歷中,取出4索引對應的 Vnode節點:

diff 過程中,如果存在 key ,並且滿足 sameVnode ,會將該 DOM 節點進行復用,否則則會創建一個新的 DOM 節點。

首先, oldStartVnode 、 oldEndVnode 與 newStartVnode 、 newEndVnode 兩兩比較,一共有 2*2=4 種比較方法。

情況一:當 oldStartVnode 與 newStartVnode 滿足 sameVnode,則 oldStartVnode 與 newStartVnode 進行 patchVnode,並且 oldStartIdx 與 newStartIdx 右移動。

情況二:與情況一類似,當 oldEndVnode 與 newEndVnode 滿足 sameVnode,則 oldEndVnode 與 newEndVnode 進行 patchVnode,並且 oldEndIdx 與 newEndIdx 左移動。

情況三:當 oldStartVnode 與 newEndVnode 滿足 sameVnode,則說明 oldStartVnode 已經跑到了 oldEndVnode 後面去了,此時 oldStartVnode 與 newEndVnode 進行 patchVnode 的同時,還需要將 oldStartVnode 的真實 DOM 節點移動到 oldEndVnode 的後面,並且 oldStartIdx 右移, newEndIdx 左移。

情況四:與情況三類似,當 oldEndVnode 與 newStartVnode 滿足 sameVnode,則說明 oldEndVnode 已經跑到了 oldStartVnode 前面去了,此時 oldEndVnode 與 newStartVnode 進行 patchVnode 的同時,還需要將 oldEndVnode 的真實 DOM 節點移動到 oldStartVnode 的前面,並且 oldStartIdx 右移, newEndIdx 左移。

當這四種情況都不滿足,則在 oldStartIdx 與 oldEndIdx 之間查找與 newStartVnode 滿足 sameVnode 的節點,若存在,則將匹配的節點真實 DOM 移動到 oldStartVnode 的前面。

若不存在,說明 newStartVnode 為新節點,創建新節點放在 oldStartVnode 前面即可。

當 oldStartIdx > oldEndIdx 或者 newStartIdx > newEndIdx,循環結束,這個時候我們需要處理那些未被遍歷到的 VNode。

當 oldStartIdx > oldEndIdx 時,說明老的節點已經遍歷完,而新的節點沒遍歷完,這個時候需要將新的節點創建之後放在 oldEndVnode 後面。

當 newStartIdx > newEndIdx 時,說明新的節點已經遍歷完,而老的節點沒遍歷完,這個時候要將沒遍歷的老的節點全都刪除。

借用官方的一幅圖:

Vue.js 實現了一套聲明式渲染引擎,並在 runtime 或者預編譯時將聲明式的模板編譯成渲染函數,掛載在觀察者 Watcher 中,在渲染函數中(touch),響應式系統使用響應式數據的 getter 方法對觀察者進行依賴收集(Collect as Dependency),使用響應式數據的 setter 方法通知(notify)所有觀察者進行更新,此時觀察者 Watcher 會觸發組件的渲染函數(Trigger re-render),組件執行的 render 函數,生成一個新的 Virtual DOM Tree,此時 Vue 會對新老 Virtual DOM Tree 進行 Diff,查找出需要操作的真實 DOM 並對其進行更新。

❽ 怎麼在預編譯加入zigbeepro

zigbee pro可以說是zigbee的升級版協議,有很多增強型的功能,比如輪流定址、多對一路由、更高的安全性能等等,另外,實際上能支持的網路節點要遠多於老版zigbee協議,更接近於商業應用。 從底層來講,zigbee與RF4CE協議都是遵循802.15.4規范的

熱點內容
scratch少兒編程課程 發布:2025-04-16 17:11:44 瀏覽:637
榮耀x10從哪裡設置密碼 發布:2025-04-16 17:11:43 瀏覽:366
java從入門到精通視頻 發布:2025-04-16 17:11:43 瀏覽:82
php微信介面教程 發布:2025-04-16 17:07:30 瀏覽:307
android實現陰影 發布:2025-04-16 16:50:08 瀏覽:789
粉筆直播課緩存 發布:2025-04-16 16:31:21 瀏覽:339
機頂盒都有什麼配置 發布:2025-04-16 16:24:37 瀏覽:210
編寫手游反編譯都需要學習什麼 發布:2025-04-16 16:19:36 瀏覽:810
proteus編譯文件位置 發布:2025-04-16 16:18:44 瀏覽:364
土壓縮的本質 發布:2025-04-16 16:13:21 瀏覽:590