編寫支持SSR的通用組件指南
介紹
作為Vue開發人員,你可能聽說過伺服器端渲染(SSR)。 即使你沒有使用像Nuxt.js或SSR-plugin這樣的框架,你也要知道如何編寫在伺服器端和客戶端都支持的通用組件。 如果你想找到基於SSR的方法或與人共享你的組件,這些知識肯定會讓你更輕鬆!如果作為一個庫/插件作者,我認為這些知識是必須掌握的。 猜猜看,它甚至都不難!
常見的陷阱
在編寫通用組件時,開發人員應該考慮三個非常常見的警告。
1.window, document, and friends - platform-specific APIs
在伺服器端處理組件時,不會發生動態更新。 這就是為什麼在伺服器上只執行兩個生命周期鉤子:beforeCreate和created。 這也意味著,這兩個鉤子將被調用兩次, 一次在伺服器上,一次在客戶端。但是在伺服器端,沒有window,document,也沒有其他特定於瀏覽器的API,如fetch。如果你試圖在這兩個鉤子中調用它們,伺服器上會拋出一個錯誤,組件就不能在伺服器端渲染了! 這只是伺服器端環境下「普通」組件或第三方庫的最常見問題。
經驗法則:不要在created或beforeCreate中調用特定於瀏覽器的API。 如果必須這樣做,那麼至少要執行可用性檢查:
export default {
created() {
if(typeof window !== "undefined"){
window.scroll(/*...*/)
}
}
}
但在大多數情況下,在beforeMount或mount中調用它們是完全沒問題的。 如果必須在伺服器和客戶端上使用API,比如要發送AJAX請求,請確保雙方都可以使用(例如使用isomorphic-fetch或axios)。此外,你有時需要在組件中用到this.$el($el是組件本身的DOM元素)。在綁定事件偵聽器或進行查詢選擇時,這可以派上用場。
2.Lifecycle hooks and side effects
說到生命周期鉤子!你應該考慮另一件事:副作用。函數或表達式在修改本地環境之外的某些狀態時具有副作用。比如API調用,I/O操作,設置計時器,添加偵聽器等。
為了避免內存泄漏,你不希望在創建和beforeCreate掛鉤中產生副作用,因為當這些鉤子也從伺服器端調用時,你無法關閉那裡的連接。相反,這些對象將永遠存在並加起來,導致內存泄漏!
經驗法則:不要在created或beforeCreate中使用帶副作用的代碼。
3.No data reactivity(數據隔離性)
這通常不是什麼大問題,但你需要知道。伺服器端和客戶端的值之間數據互不影響。如果你在伺服器端操作data,則根本不會在客戶端看到這些變更。
指令(Directives)
自定義Vue指令經常用於操縱DOM(例如,在滾動時顯示元素或使元素固定到特定位置)。我們知道這在伺服器端不起作用。那有什麼解決辦法呢?
嗯,最簡單的方法是:不要使用Directives,使用component。我使用VueNextLevelScroll或vue-if-bot等組件做到了這一點,因為它更容易使它們普遍可用,並且它們也可以進行代碼分割!使用components抽離,你不會失去任何東西。
如果你確實想使用指令,則可以在伺服器端添加相同效果的一個指令。在Nuxt中,可以通過在nuxt.config.js中的this.options.render.bundleRenderer對象中設置指令對象來實現。一個好的(但很複雜的)例子是官方的v-model ssr指令。
注意:請注意以kebab-case(如:make-red而不是makeRed)傳遞你的指令。否則,他們將無法被識別!這是vue-server-renderer中的錯誤(有關詳細信息,請看官方文檔)。
總結
使用特定平台的API時要特別小心,尤其是window和document。 請記住,created和beforeCreate是在伺服器端和客戶端都會執行的。確保寫的時候沒有副作用,沒有window,伺服器端數據變更不會表現在客服端。使用指令並不總是最好的抽離方法。但是如果你確實使用它們,請提供伺服器端指令 如果你想進一步閱讀,我建議你閱讀官方的vue-ssr-docs!
打開今日頭條,查看更多精彩圖片※「並發編程」Future模式及JDK中的實現
※MySQL操作之DCL
TAG:程序員小新人學習 |