摘要:原文鏈接開發一個單頁面應用,相信很多前端工程師都已經學會了,但是單頁面應用有一個致命的缺點,就是極不友好。基于它,我們可以快速開發一個基于的單頁面應用。只有數據流存在相關配置時可用。引入后,所有頁面均有效。
原文鏈接
Vue 開發一個單頁面應用,相信很多前端工程師都已經學會了,但是單頁面應用有一個致命的缺點,就是 SEO 極不友好。除非,vue 能在服務端渲染(ssr)并直接返回已經渲染好的頁面,而并非只是一個單純的 。
Nuxt.js 就是一個極簡的 vue 版的 ssr 框架。基于它,我們可以快速開發一個基于 vue 的 ssr 單頁面應用。
安裝Nuxt.js 官方提供了一個模板,可以使用 vue-cli 直接安裝。
$ vue init nuxt-community/starter-template目錄結構
. ├── README.md ├── assets ├── components ├── layouts ├── middleware ├── node_modules ├── nuxt.config.js ├── package.json ├── pages ├── plugins ├── static ├── store └── yarn.lock
其中:
assets: 資源文件。放置需要經過 webpack 打包處理的資源文件,如 scss,圖片,字體等。
components: 組件。這里存放在頁面中,可以復用的組件。
layouts: 布局。頁面都需要有一個布局,默認為 default。它規定了一個頁面如何布局頁面。所有頁面都會加載在布局頁面中的
middleware: 中間件。存放中間件。可以在頁面中調用: middleware: "middlewareName" 。
pages: 頁面。一個 vue 文件即為一個頁面。index.vue 為根頁面。
若需要二級頁面,則添加文件夾即可。
如果頁面的名稱類似于 _id.vue (以 _ 開頭),則為動態路由頁面,_ 后為匹配的變量(params)。
若變量是必須的,則在文件夾下建立空文件 index.vue。更多的配置請移步至 官網 。
plugin: 插件。用于組織那些需要在 根vue.js應用 實例化之前需要運行的 Javascript 插件。需要注意的是,在任何 Vue 組件的生命周期內, 只有 beforeCreate 和 created 這兩個鉤子方法會在 客戶端和服務端均被調用。其他鉤子方法僅在客戶端被調用。
static: 靜態文件。放置不需要經過 webpack 打包的靜態資源。如一些 js, css 庫。
store: 狀態管理。具體使用請移步至 官網。
nuxt.config.js: nuxt.config.js 文件用于組織Nuxt.js 應用的個性化配置,以便覆蓋默認配置。具體配置請移步至 官網。
Nuxt 特有函數首先,了解一下在 nuxt 的頁面中獨有的函數/變量:
asyncData(context)asyncData方法使得你能夠在渲染組件之前異步獲取數據。該方法在服務端中執行的,所以,請求數據時,不存在跨域問題。返回的數據將與 data() 返回的數據進行合并。由于asyncData方法是在組件 初始化 前被調用的,所以在方法內是沒有辦法通過 this 來引用組件的實例對象。
context 變量的可用屬性一覽:
屬性字段 | 類型 | 可用 | 描述 |
---|---|---|---|
isClient | Boolean | 客戶端 & 服務端 | 是否來自客戶端渲染 |
isServer | Boolean | 客戶端 & 服務端 | 是否來自服務端渲染 |
isDev | Boolean | 客戶端 & 服務端 | 是否是開發(dev) 模式,在生產環境的數據緩存中用到 |
route | vue-router 路由 | 客戶端 & 服務端 | vue-router 路由實例。 |
store | vuex 數據流 | 客戶端 & 服務端 | Vuex.Store 實例。只有vuex 數據流存在相關配置時可用。 |
env | Object | 客戶端 & 服務端 | nuxt.config.js 中配置的環境變量, 見 環境變量 api |
params | Object | 客戶端 & 服務端 | route.params 的別名 |
query | Object | 客戶端 & 服務端 | route.query 的別名 |
req | http.Request | 服務端 | Node.js API 的 Request 對象。如果 nuxt 以中間件形式使用的話,這個對象就根據你所使用的框架而定。nuxt generate 不可用。 |
res | http.Response | 服務端 | Node.js API 的 Response 對象。如果 nuxt 以中間件形式使用的話,這個對象就根據你所使用的框架而定。nuxt generate 不可用。 |
redirect | Function | 客戶端 & 服務端 | 用這個方法重定向用戶請求到另一個路由。狀態碼在服務端被使用,默認 302。redirect([status,] path [, query]) |
error | Function | 客戶端 & 服務端 | 用這個方法展示錯誤頁:error(params)。params 參數應該包含 statusCode 和 message 字段。 |
fetch 方法用于在渲染頁面前填充應用的狀態樹(store)數據, 與 asyncData 方法類似,不同的是它不會設置組件的數據。為了讓獲取過程可以異步,你需要返回一個 Promise,Nuxt.js 會等這個 promise 完成后再渲染組件。
fetch 會在組件每次加載前被調用(在服務端或切換至目標路由之前)。
headNuxt.js 使用了 vue-meta 更新應用的 頭部標簽(Head) 和 html 屬性。
用于更新 頭部信息。如 title,descripe 等。在 head 方法里可通過 this 關鍵字來獲取組件的數據。
layout指定該頁面使用哪個布局文件。默認值為 default。
middleware需要執行的中間件,如鑒權的 auth等。
transition指定頁面切換時的動畫效果。支持傳入 String, Object, Function。具體配置請移步至 官網 。
validateNuxt.js 可以讓你在動態路由對應的頁面組件中配置一個校驗方法用于校驗動態路由參數的有效性。
返回 true 說明路由有效,則進入路由頁面。返回不是 true 則顯示 404 頁面。
Begin Coding 前置工作在這里,我們使用 CNode API 進行開發 Demo.
請求數據,我們使用 Nuxt 官方提供的 @nuxtjs/axios 安裝后,在 nuxt.config.js 中加上:
export default { ... modules: [ "@nuxtjs/axios" ], axios: { baseURL: "https://cnodejs.org/api/v1", // or other axios configs. } ... }
就可以在頁面中通過 this.$axios.$get 來獲取數據,不需要在每個頁面都多帶帶引入 axios.
需要先安裝 sass-loader 和 node-sass
$ yarn add sass-loader node-sass --dev
如果需要在項目中全局使用某個 scss 文件(如 mixins, vars 等),需要借助 sass-resources-loader : yarn add sass-resources-loader —dev, 還需要在 nuxt.config.js 的 build 配置中調整導出的 loader 配置:
export default { ... build: { extend(config, { isDev, isClient }) { const sassResourcesLoader = { loader: "sass-resources-loader", options: { resources: [ // 填寫需要全局注入 scss 的文件。引入后,所有頁面均有效。 "assets/styles/mixins.scss" ] } } // 修改 scss sass 引用的 loader。 config.module.rules.forEach((rule) => { if (rule.test.toString() === "/.vue$/") { rule.options.loaders.sass.push(sassResourcesLoader) rule.options.loaders.scss.push(sassResourcesLoader) } if (["/.sass$/", "/.scss$/"].indexOf(rule.test.toString()) !== -1) { rule.use.push(sassResourcesLoader) } }) } } ... }首頁
首頁一般只需要簡單的獲取首頁數據并渲染即可。
主要 代碼:
asyncData({app, query}) { console.log(query) // 根據不用的標簽獲取不同的數據,最后返回話題列表。 return app.$axios.$get(`topics?tab=${query.tab || ""}`).then(res => { // console.log(res) // console.log(JSON.parse(res)) return {list: res.data} }) }
當進入首頁時,該函數會被執行, nuxt 會等到獲取數據后再和組件的 data 合并,進而渲染數據。在模板中,可以直接使用 list 變量獲取數據。
{{topic.title}} 精華 {{tabsObj[topic.tab]}} 和 的區別是: nuxt-link 走的是 vue-router 的路由,即網頁已為單頁面,并且瀏覽器不會重定向。而 a 標簽走的是 window.location.href,每一次點擊 a 標簽后的頁面,都會進行一次服務端渲染,和普通的 PHP 混合開發沒有太大的區別。
在這里使用了 nuxt-link 是因為 CNode 的 API 不存在跨域問題,因此可以作為一個單頁面應用,體驗更好。
因為列表頁數據類型有多種,該頁面可能會被復用,所以當路由對象發生變化時,需要重新獲取數據,這時可以監聽路由的變化以做出響應:
watch: { "$route": function() { console.log("$route has changed.") this.getData() } }配置 seo 優化(這里只是單純的復制罷了,demo 使用,侵刪):
head() { return { title: "首頁" + (this.$route.query.tab ? `- ${this.tabsObj[this.$route.query.tab]}` : ""), meta: [{ hid: "description", name: "description", content: "CNode:Node.js專業中文社區" }] } }話題詳情同樣的,使用 asyncData 函數進行獲取數據,再渲染頁面。
asyncData({app, params}) { console.log(params) return app.$axios.$get("topic/" + params.id).then(res => { // let data = res.data instanceof String ? JSON.parse(res.data) : res.data let data = res.data // console.log(res) // let div = document.createElement("div") // div.innerHTML = res.data.data.content // res.data.summary = div.innerText.substr(0, 120) data.summary = data.content.replace(/<[^>]+>/g,"").substr(0, 120).replace(/s+/g, "") return {detail: data} }).catch(err => { console.log("axios.get failed.") console.error(err) }) }在這里,踩過坑。想使用 div 的 innerText 來過濾掉正文中的 HTML 標簽,但是,如果用戶是直接進入這個頁面的時候,執行 asyncData 時,document 對象是不存在的,從而會報錯。也就是說,當 asyncData 在服務端執行時,是沒有 document 和 window 對象的,請大家注意一下。
作為一個社區,seo 尤為重要,倘若每個頁面都需要寫一大堆的 head 對象,就會顯得尤其的繁瑣。所以可以借助 nuxt 的 plugin 機制,將其封裝成一個函數,并注入到每一個頁面當中:
// plugins/global.js import Vue from "vue" Vue.mixin({ methods: { // 必傳 標題,描述。其他的 meta 標簽通過 payload 注入,其中,每個 meta 的 hid 需要是唯一的。 $seo(title, content, payload = []) { return { title, meta: [{ hid: "description", name: "description", content }].concat(payload) } } } })在 nuxt.config.js 中加上:
export default { plugins: [ "~plugins/global.js" ] }這樣,只需要在頁面的 head 的函數中,返回該函數即可:
head() { return this.$seo(this.detail.title, this.detail.summary) }可見,詳情頁已經成功的設置了部分 seo 的標簽。
以上是 Nuxt 的一些基礎配置及應用。
我再去研究一下, fetch 和 store 的結合,將該 demo 繼續完善。
Demo 線上地址
GitHub 地址文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107253.html
相關文章
珠峰前端架構師培養計劃
摘要:公司的招聘要求都提到了至少熟悉其中一種前端框架,有前端工程化與模塊化開發實踐經驗相關字眼。我們主要從端公眾號移動端小程序三大平臺進行前端的技術選型,并來說說選其技術的幾大優勢。技術的優勢互聯網前端大潮后,前端出現了大框架,分別是與。 1、技術選型的背景前端技術發展日新月異,互聯網上出現的新型框架也比較多,如何讓新招聘的人員...
Docker部署基于Nodejs的Web應用-實戰篇
摘要:采用虛擬化的技術來虛擬化出應用程序的運行環境。安裝成功后,可以通過查看版本號盡量使用最新的穩定版本。是鏡像名,是鏡像的版本號,到此你已經成功構建了一個新的鏡像,你可以通過,查看你的鏡像。部署時將此文件到生產環境服務器上。 Docker docker是一個開源的應用容器引擎,可以為我們提供安全、可移植、可重復的自動化部署的方式。docker采用虛擬化的技術來虛擬化出應用程序的運行環境。此...
Docker部署基于Nodejs的Web應用-實戰篇
摘要:采用虛擬化的技術來虛擬化出應用程序的運行環境。安裝成功后,可以通過查看版本號盡量使用最新的穩定版本。是鏡像名,是鏡像的版本號,到此你已經成功構建了一個新的鏡像,你可以通過,查看你的鏡像。部署時將此文件到生產環境服務器上。 Docker docker是一個開源的應用容器引擎,可以為我們提供安全、可移植、可重復的自動化部署的方式。docker采用虛擬化的技術來虛擬化出應用程序的運行環境。此...
Vue現有項目改造為Nuxt項目
摘要:好了,項目啟動了,目錄結構也清楚了,接下來就是整個現有項目的遷移了目前正在改造項目,文章尚未寫完,會抽時間不定期的繼續更新項目的改造過程及分享改造過程中遇到的問題 公司項目,最初只為了實現前后端分離式開發,直接選擇了vue框架進行開發,然而現在項目基本完成了,發現蜘蛛根本就抓取不到網站數據,搜索引擎搜出來,都是一片空白沒有數據,需要對項目做SEO優化。 本人第一次接觸SEO的優化,完全...
發表評論
0條評論
閱讀 1597·2023-04-25 14:12
閱讀 1070·2021-08-27 16:24
閱讀 2533·2019-08-30 15:44
閱讀 2912·2019-08-30 13:16
閱讀 1665·2019-08-29 14:10
閱讀 966·2019-08-29 13:54
閱讀 1296·2019-08-29 13:09
閱讀 1803·2019-08-26 18:37