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