追求完美,相信你們都是這樣的。由於先後端分離的弊端性,在項目構建時,瀏覽器並不會捕捉到項目的內容,因此開始,筆者決定引入nuxt.js文件來配合vue完成Server Slider Render博客系統開發。服務端渲染如下簡稱SSR,不知道nuxt的童鞋能夠去nuxt官網瞭解一哈。vue
聲明:一下代碼案例結合vue理解。mysql
剛入坑,感受步履維艱。想運來的使用方式,編輯器並不會報錯。可是瀏覽器卻報的nuxt錯誤。web
後來通過幾十根頭髮的代價換來了插件的正確使用方式sql
demo引入第三方的特效插件 vuex
須要如今plugins中寫一個第三方文件的js文件,這裏是筆者引入的一個vue的特效的插件,數據庫
在nuxt.config.js中進行引入npm
/*
** Plugins to load before mounting the App
*/
這裏須要補充的是,ssr爲是否開啓SSRelement-ui
最後在組件中就可使用: json
<template> <section class="container"> <vue-particles color="#fff" :particleOpacity="0.7" :particlesNumber="60" shapeType="circle" :particleSize="4" linesColor="#fff" :linesWidth="1" :lineLinked="true" :lineOpacity="0.4" :linesDistance="150" :moveSpeed="2" :hoverEffect="true" hoverMode="grab" :clickEffect="true" clickMode="push" class="lizi" > </vue-particles> <nuxt /> </section> </template>
最後查看效果如圖:

效果如上,成功引入。
補充這個時候發現是沒問題,可是當咱們更改dom節點,放到到全屏的時候,依然能夠,可是控制檯爆出vue警告:
commons.app.js:13349 [Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render
這個坑,真的坑了我很久,最後才發現,有些插件是不支持SSR的,恰好vue-partiles就是其中之一。
解決辦法:引入時經過no-ssr標籤包裹就
<no-ssr><vue-particles color="#ffffff" :particleOpacity="0.7" :particlesNumber="80" shapeType="circle" :particleSize="4" linesColor="#fff" :linesWidth="1" :lineLinked="true" :lineOpacity="0.4" :linesDistance="150" :moveSpeed="2" :hoverEffect="true" hoverMode="grab" :clickEffect="true" clickMode="push" class="lizi" > </vue-particles></no-ssr>
此組件只在客戶端呈現,意味着,使用該組件包裹的內容都不屬於SSR,在網頁源碼中都不可見。這點須要注意。
前言:這裏要區別一下vue的路由,vue路由可自行配置,靈活方便。而nuxt構建的項目,路由的配置則是由pages文件夾目錄生成。
直接上圖,所謂一圖頂千言:

這個文件夾在路由的配置中也扮演了至關重要的角色。它又是幹什麼的呢?
layouts文件字面理解多佈局,項目的總體框架通常都有其固定的底層Layouts Model,nuxt很好的實踐了這個思想。layouts文件夾的功能簡單說局勢防止通用的佈局模型,能夠爲Error Model,Default Model,固然這也是最經常使用的。固然若是說開發響應式項目,能夠多一個webAPP的底層佈局。
這個時候就淫問了,局部跳轉,vue通常採用嵌套路由實現,這裏怎麼作呢?
兩種方式:
layouts爲底,引入header,footer固定,section部分做爲<nuxt/>動態跳轉
default.vue爲默認引入的佈局模型,不須要刻意引入。
只須要在頁面中添加
<template> <section> This is my projects!; </section> </template> <script> export default { layout: 'login' } </script> <style lang="less" scoped> </style>
Layout: 構建的Layouts Model
實現的效果爲頭部固定,底部固定,中間部分跳轉
路由的配置由pages目錄生成,咱們是否能夠修改pages目錄來完成嵌套路由呢?
這裏,考慮到文件目錄的層級,博主這裏並未採用此方法,單此方法確實可行。
這裏給你們一個error的組件,你們能夠直接賦值,不須要引如,在報錯時,該組件會默認執行
3.動態路由
暫未實踐
<template> <div class="error"> <!-- <img src="../assets/img/logo.png" alt="Nuxt.js Logo" class="logo" /> --> <h1 class="title"> {{ error.statusCode }} </h1> <h2 class="info"> {{ error.message }} </h2> <nuxt-link to="/">首頁</nuxt-link> </div> </template> <script> export default { props: ['error'] } </script> <style scoped> .error { text-align: center; padding: 30px 0; } .title { margin-top: 15px; font-size: 5em; } .info { font-weight: 300; color: #9aabb1; margin: 0; } a { margin-top: 50px; border: 1px solid #3084bb; color: #3084bb; font-size: 16px; display: inline-block; padding: 10px 20px; border-radius: 4px; } </style>
對於不相鄰組件以及其餘需求,狀態庫老是一個很好的狀態存儲工具。
回顧vue中vuex的使用,項目根文件夾創建store文件夾。建立index.js文件,然後在main.js主入口文件中引入該文件,並掛在到vue原型鏈上,日後餘生,咱們即可經過this.$store來使用
可是在nuxt中,並無main.js主入口文件,咱們又如何使用呢?
官方註釋:
爲了讓 Vue 使用 Vuex,咱們引入
Vue
和Vuex
(Nuxt.js 已包含),這樣組件內就多了個$store
屬性了
這個是官方解釋,說明Nuxt中已經包含了Vuex,咱們只須要經過this.$store就能夠訪問到。
demo:
store下新建index.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) // require('whatwg-fetch'); const store = () => new Vuex.Store({ state: { searchParams: '', }, mutations: { setSearch: function (state, params) { state.searchParams = params; } }, actions: { } }) export default store
<template> <header> <div class="search"> <input type="text" v-model="searchContent"><button @click="search(searchContent)">Search</button> </div> </header> </template> export default { data() { return { searchContent: '', } }, methods: { search(data) { this.$store.commit('setSearch',data); console.log(this.$store.state); }, } } </script>
簡單的使用就是如此了,固然提交更改等操做與vue中vuex的操做都是同樣的,關鍵問題是如何引入。
這裏我將權限校驗分爲兩部分一個是前端根據路由處理,一個是後端根據接口處理
前端作的處理以下:
有些頁面在不登陸的狀況是不容許登陸的,在路由發生變化的時候進行判斷,是否含有token,若是有則進行next()跳轉,若是沒有則跳轉login
後端的處理以下:
針對於某些接口,在沒有登陸的狀況下,某些接口是沒法進行調用的,除非登陸成功token有效。若是前端在調用某接口的時候,先判斷是否攜帶token過來,且token是否有效,若是有效,
則繼續條用接口,若是token失效或者headers中沒有攜帶token則返回401並給出詳情提示'unAuthorization'
下來咱們一步步進行處理,咱們先進行前端的處理
middleware中間件的使用
官方解釋:中間件容許您定義一個自定義函數運行在一個頁面或一組頁面渲染以前。
每個中間件應放置在
middleware/
目錄。文件名的名稱將成爲中間件名稱(middleware/auth.js
將成爲auth
中間件)。
簡單說就是能夠針對某一模塊或某一頁面進行設置中間件,而中間件的使用,則能夠進行權限的一個校驗。
上Code:
import { isLogin } from '../util/assist'; export default function({ route, req, res, redirect }) { let isClient = process.client; let isServer = process.server; let redirectURL = '/login'; if(isServer) { let cookies = req.cookies; let path = req.originalUrl; if(path.indexOf('admin') !== -1 && !cookies.token) { redirect(redirectURL); } } if(isClient) { if(route.path.indexOf('admin') !== -1 && !isLogin()) { redirect(redirectURL); } } }
isLogin
export function isLogin() { if (getCookieInClient('token')) { return true } return false } export function getCookieInClient(name) { let arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); if (arr = document.cookie.match(reg)) return unescape(arr[2]); else return null; }
代碼寫完了,咱們在什麼地方引用呢?
咱們這裏採用全局引用,引入的模塊的名稱就是中間件中文件的名稱。
nuxt.config.js
router: { middleware: 'adminAuth' },
這裏之因此寫成admin是由於,我的項目的設置,admin爲項目的管理模塊,都已admin開頭,因此這裏統一設置。
後端又如何進行設置呢?
let jwt = require('jwt-simple'); const jwtSecret = require('../util/database.config').jwtSecret const needAuth = require('../../util/api.config').needAuth module.exports = function (req, res, next) { let path = req.originalUrl.split('?')[0]; console.log('7',path); console.log('8',needAuth); //接口不須要登錄:直接next if (needAuth.indexOf(path) == -1) { return next(); } //接口須要登錄 var token = req.headers['authorization']; if (!token) { return res.json({ code: 401, message: 'you need login:there is no token' }) } try { //解密獲取的token let decoded = jwt.decode(token, jwtSecret); //校驗有效期 if (decoded.exp <= Date.now()) { return res.json({ code: 401, message: 'you need login:token is expired' }); } next(); } catch (err) { return res.json({ code: 401, message: 'you need login:decode token fail' }) } };
api.config.js: 防止須要驗證的接口
jwtSecret: 能夠爲任意字符串
jwt-simple: token的生成加密與解析詳見:https://www.jianshu.com/p/d9a087349ed2
模糊搜索
sqlTitle =
select * from articles where title like '%${params.search}%';
;like操做符: LIKE做用是指示mysql後面的搜索模式是利用通配符而不是直接相等匹配進行比較.
若是要模糊查詢,還要加上
通配符'%'
匹配以"nuxt"開頭的數據
select * from articles where title like 'nuxt&'匹配包含'nuxt'的數據select * from articles where title like '%nuxt%';匹配以'nuxt'結尾的數據select * from articles where title like '%nuxt';通配符二 '_'
和'%'相似,不過會作出一個字符的限制,限制字符爲幾位
eg:
數據庫中含有數據
123,1234,12345.
'2_' 意思是以2開頭後面只有一位 結果爲123
'_2' 意思是以2結果,前面只有一位 結果爲 null,由於沒有2結尾的
場景:一個標籤表,一個文章表。
經過標籤的名稱去查,該標籤下全部的文章的id的行。
SELECT second.* from articles_tags first LEFT JOIN articles second on second.id = first.article_id WHERE tag = 'vue.js'
這個的意思是:查詢表二符合條件的全部數據,查詢條件呢?
符合條件的全部的tag的名稱的這一行的article_id。而後根據這個article_id去articles表中查詢相關的全部數據。
數據庫如圖:
正如所見, MySQL的通配符頗有用。但這種功能是有代價的:通配符搜索的處理通常要比前面討論的其餘搜索所花時間更長。這裏給出一些使用通配符要記住的技巧。
在確實須要使用通配符時,除非絕對有必要,不然不要把它們用 在搜索模式的開始處。把通配符置於搜索模式的開始處,搜索起來是最慢的。
仔細注意通配符的位置。若是放錯地方,可能不會返回想要的數