原文來自:https://blog.lichter.io/posts/the-guide-to-write-universal-ssr-ready-vue-compon?css
utmcampaign=Vue.js%20News&utmmedium=email&utm_source=Revue%20newsletter
html
做爲Vue開發者。你可能據說過server端渲染(SSR)。 即便你沒有使用像Nuxt.js或SSR-plugin這種框架,你也要知道怎樣編寫在server端和client都支持的通用組件。vue
假設你想找到基於SSR的方法或與人共享你的組件,這些知識確定會讓你更輕鬆!假設做爲一個庫/插件做者。我以爲這些知識是必須掌握的。 猜猜看,它甚至都不難!react
在編寫通用組件時。開發者應該考慮三個非常常見的警告。ios
1.window, document, and friends - platform-specific APIsaxios
在server端處理組件時,不會發生動態更新。 這就是爲何在server上僅僅運行兩個生命週期鉤子:beforeCreate和created。 這也意味着,這兩個鉤子將被調用兩次, 一次在server上。一次在client。瀏覽器
但是在server端。沒有window,document。也沒有其它特定於瀏覽器的API,如fetch。假設你試圖在這兩個鉤子中調用它們,server上會拋出一個錯誤,組件就不能在server端渲染了。 這僅僅是server端環境下「普通」組件或第三方庫的最多見問題。app
經驗法則:不要在created或beforeCreate中調用特定於瀏覽器的API。 假設必須這樣作,那麼至少要運行可用性檢查:框架
export default {
ide
created() {
if(typeof window !== 'undefined'){
window.scroll(/*...*/)
}
}
}
但在大多數狀況下。在beforeMount或mount中調用它們是全然沒問題的。 假設必須在server和client上使用API,比方要發送AJAX請求,請確保兩方都可以使用(好比使用isomorphic-fetch或axios)。此外,你有時需要在組件中用到this.$el($el是組件自己的DOM元素)。
在綁定事件偵聽器或進行查詢選擇時,這可以派上用場。
2.Lifecycle hooks and side effects
說到生命週期鉤子。你應該考慮還有一件事:反作用。
函數或表達式在改動本地環境以外的某些狀態時具備反作用。比方API調用,I/O操做,設置計時器。加入偵聽器等。
爲了不內存泄漏,你不但願在建立和beforeCreate掛鉤中產生反作用,因爲當這些鉤子也從server端調用時,你沒法關閉那裏的鏈接。
相反,這些對象將永遠存在並加起來,致使內存泄漏。
經驗法則:不要在created或beforeCreate中使用帶反作用的代碼。
3.No data reactivity(數據隔離性)
這一般不是什麼大問題。但你需要知道。server端和client的值之間數據互不影響。假設你在server端操做data。則根本不會在client看到這些變動。
本身定義Vue指令經常用於操縱DOM(好比。在滾動時顯示元素或使元素固定到特定位置)。
咱們知道這在server端不起做用。
那有什麼解決的方法呢?
嗯,最簡單的方法是:不要使用Directives,使用component。我使用VueNextLevelScroll或vue-if-bot等組件作到了這一點。因爲它更easy使它們廣泛可用,並且它們也可以進行代碼切割!使用components抽離。你不會失去不論什麼東西。
假設你確實想使用指令,則可以在server端加入一樣效果的一個指令。在Nuxt中,可以經過在nuxt.config.js中的this.options.render.bundleRenderer對象中設置指令對象來實現。一個好的(但很是複雜的)樣例是官方的v-model ssr指令。
注意:請注意以kebab-case(如:make-red而不是makeRed)傳遞你的指令。
不然,他們將沒法被識別!這是vue-server-renderer中的錯誤(有關具體信息,請看官方文檔)。
使用特定平臺的API時要特別當心,尤爲是window和document。
請記住,created和beforeCreate是在server端和client都會運行的。
確保寫的時候沒有反作用,沒有window。server端數據變動不會表現在客服端。
使用指令並不老是最好的抽離方法。
但是假設你確實使用它們,請提供server端指令 假設你想進一步閱讀。我建議你閱讀官方的vue-ssr-docs!