如何用Vue+Vuetify快速建站?

懂點(diǎn)基礎(chǔ),學(xué)點(diǎn)套路,輕松用 Vue 寫個(gè)網(wǎng)站

幾個(gè)月前用 Vue + Vuetify 這一套框架寫了個(gè) 倉庫管理系統(tǒng) 和 個(gè)人網(wǎng)站,近來不寫前端了,所以整理了如何用 Vue,Vuetify,Vuex,Vue-router 寫一個(gè)單頁應(yīng)用 (SPA),為以后回憶方便,也供初學(xué)者參考,少踩坑。

(這篇不是 Vue 的基礎(chǔ)介紹,所以建議先讀了 Vue 的官方文檔,再來看怎么應(yīng)用。)

這篇以開發(fā)的個(gè)人網(wǎng)站為例,從一個(gè)空文件夾開始講到完整個(gè)網(wǎng)站,其中包括這幾個(gè)模塊:

  1. 配置開發(fā)環(huán)境
  2. 配置 Webpack
  3. 將 Vuex + Vue-router + Vue-router-sync + Vuetify 整合到整個(gè)

(代碼參考 https://github.com/weimingwill/personal-website 。整個(gè)代碼的文件結(jié)構(gòu)和重要文件放在下面,可以邊讀邊參考。結(jié)構(gòu)如下:)

.
├── package.json
├── webpack.config.js
├── node_modules
├── build
│   ├── utils.js
│   └── vue-loader.conf.js
├── config
│   ├── dev.env.js
│   ├── index.js
│   ├── prod.env.js
│   └── test.env.js
├── src
│   ├── assets
│   │   ├── images
│   ├── css
│   │   ├── google-material-icons.css
│   │   └── main.css
│   ├── router
│   │   └── index.js
│   ├── store
│   │   ├── actions.js
│   │   ├── getters.js
│   │   ├── index.js
│   │   ├── modules
│   │   │   ├── app.js
│   │   │   ├── contacts.js
│   │   │   ├── menu
│   │   │   │   ├── index.js
│   │   │   │   └── lazyLoading.js
│   │   │   ├── projects.js
│   │   │   └── skills.js
│   │   └── mutation-types.js
│   ├── index.html
│   ├── main.js
│   ├── App.vue
│   └── views
│       ├── About.vue
│       ├── Blog.vue
│       ├── Contact.vue
│       ├── Resume.vue
│       ├── Skills.vue
│       ├── layout
│       │   ├── AppMain.vue
│       │   ├── Sidebar.vue
│       │   └── Toolbar.vue
│       └── projects
│           ├── Projects.vue
│           └── components
│               └── ProjectCard.vue

配置開發(fā)環(huán)境

首先,確保系統(tǒng)安裝了 Node.js,安裝 Node.js 的同時(shí)也安裝了 npm。

創(chuàng)建一個(gè)新的文件夾,在這個(gè)文件夾里進(jìn)行初始化:

npm init

根據(jù)提示,填入對(duì)應(yīng)信息,完成后會(huì)自動(dòng)生成 package.json 文件,填入的信息都可以在這個(gè)文件下做更改。下一步是安裝開發(fā)需要的庫:

npm install vue
npm install webpack
...
...

執(zhí)行后,會(huì)自動(dòng)下載庫到根目錄下的 node_modules 里。因?yàn)?Vue 有一些要用的庫,webpack 還有許多要用的庫,一一安裝比較麻煩,可以直接去我的 Github 上面復(fù)制 package.json 里買的內(nèi)容,替換本地的文件內(nèi)的內(nèi)容,然后執(zhí)行

npm install

所有需要的東西應(yīng)有盡有。到這里就完成了最基本的環(huán)境配置。

Webpack 配置

什么是 Webpack ?Webpack 是一個(gè)打包器,能夠?qū)⒏鞣N不同格式的 js, css, jpg 等等,打包成一個(gè)或幾個(gè)js文件,然后可以直接在 html 里使用打包后的文件,減少了各個(gè)文件之間相互依賴的麻煩。Webpack 入門可以參考早些寫的文章 Wepack快速入門實(shí)踐

Webpack 主配置文件是 webpack.config.js,另外有一些配置文件分別在 buildconfig 文件夾里,可以直接將這三個(gè)復(fù)制項(xiàng)目根目錄,重點(diǎn)講下 Webpack 里比較重要的地方。

  1. 起始點(diǎn)和輸出
  entry: {
    app: './src/main.js'
  },
  output: {
    path: path.resolve(__dirname, ''),
    filename: 'app.js'
  },
module: {
...
}

這里使用 src 文件下的 main.js 作為 Webpack 執(zhí)行的起始點(diǎn),將 module 下面定義了的各種不同文件格式,通過不同的 loader,在執(zhí)行后,自動(dòng)打包成根目錄下的 app.js。( main.js 是最主要的一個(gè) js 文件,具體內(nèi)容稍后分解。)

  1. HtmlWebpackPlugin 使用 src 文件下的 index.html 作為模版,在執(zhí)行后,自動(dòng)在根目錄下生成 index.html 不同的地方是,根目錄下的這個(gè)文件,包含了前面提到的自動(dòng)生成的 app.js
<script type="text/javascript" src="app.js"></script>
  1. 怎么執(zhí)行 webpack?
npm run dev

在根目錄下運(yùn)行上面代碼就可以運(yùn)行 webpack 進(jìn)行打包,原因是在 package.json 文件里,在 scripts 里定義了這個(gè)命令。

{
  "scripts": {
    "dev": "webpack -d --watch",
    "test": "echo \"Error: no test specified\" && exit 1"
  }, ...
}

到這里就完成了最重要的兩部分基礎(chǔ)配置,接下來是如何用 Vue, Vuetify, Vuex, Vue-router, Vue-router-sync。

Vuetify + Vuex + Vue-router + Vue-router-sync

這里側(cè)重講怎么將這些都結(jié)合在一起使用,每個(gè)庫的細(xì)節(jié)還是要大家自己去看官方文檔,每個(gè)官方文檔鏈接附錄在最后。這些庫主要通過一個(gè)文件結(jié)合使用 src/main.js

// src/main.js
import Vue from 'vue'
import Vuetify from 'vuetify'
import App from './App'
import store from './store'
import router from './router'
import { sync } from 'vuex-router-sync'

Vue.use(Vuetify);
sync(store, router);

new Vue({
  el: '#app',
  router,
  store,
  template: '<App/>',
  components: { App }
});

Vuetify

Vuetify 是基于 Vue 的前端組件框架,設(shè)計(jì)樣式用的是 Google Material Design。

import Vue from 'vue'
import Vuetify from 'vuetify'
Vue.use(Vuetify);

這三行代碼,實(shí)現(xiàn)了加載并使用 Vuetify。

import App from './App'
new Vue({
  el: '#app',
  router,
  store,
  template: '<App/>',
  components: { App }
});

先忽略 router 和 store。這里先是加載了 src/App.vue,這個(gè)文件是使用 Vuetify 的起始文件。

// src/App.vue
<div id="app">
  <v-app>......</v-app>
</div>

el: #app 指向的就是這里的 id="app"。所有其他組件都是寫在 <v-app></v-app> 之間的,通常是在這頁定義出整個(gè)應(yīng)用的模版,比如 sidebar,navigation bar 和主要區(qū)域。然后再根據(jù)不同的頁面,創(chuàng)建不同的 .vue 文件,通常每個(gè)頁面都是一個(gè)單獨(dú)的文件,有公用的模塊可以寫在一個(gè)地方。

Vuex

Vuex 是一個(gè)狀態(tài)管理器,對(duì)應(yīng)的是 src/store 下面的代碼,Vuex 主要概念有 state, getters, mutations, actions 和 modules。全局的 gettersactions 寫在 src/store/getters.jssrc/store/actions.js 里,在 Vuetify 中提到每有一個(gè)單獨(dú)的 .vue 文件,每個(gè) vue 的文件都可以抽象當(dāng)成一個(gè) module,每個(gè)
module 有單獨(dú)的 .js 與之對(duì)應(yīng),里面包含了這個(gè)頁面的 state, getters, mutations, actions。舉個(gè)例子,我們有一個(gè) Contact.vue 文件,對(duì)應(yīng)的 src/store/modules 里有一個(gè) contacts.js 文件,如下:

// src/store/modules/contacts.js
import * as types from '../mutation-types'

const state = {
  contacts: []
}

const getters = {
  contacts: state => state.contacts,
}

const mutations = {
  [types.READ_CONTACTS] (state) {
    let contactMethods = require('../../assets/contact-methods.json')
    state.contacts = contactMethods.methods
  }
}

const actions = {
  readContacts ({commit}) {
    commit(types.READ_CONTACTS);
  }
}

export default {
  state,
  getters,
  mutations,
  actions
}

這樣的文件結(jié)構(gòu)的好處是讓每個(gè)頁面都是相對(duì)獨(dú)立的,邏輯,代碼都比較清晰。

Vuex 里另外一個(gè)要提的是 modules 里有另外一個(gè)文件夾 menu,顧名思義,是整個(gè)應(yīng)用的目錄。代碼如下

const state = {
  items: [
    {
      title: 'Projects',
      path: '/projects',
      isMenu: true,
      router: true,
      icon: 'computer',
      component: lazyLoading('projects/Projects'),
    },...
  ]
}

具體定義了每一個(gè)組件(component) 的名字,圖標(biāo),位置,路由的地址等,具體怎么實(shí)現(xiàn)路由的稍后在 Vue-router 里細(xì)說,這里重點(diǎn)看 Lazyloading() 這個(gè)函數(shù)。

// src/store/modules/menu/lazyloading.js
export default (name, index = false) => () => require.ensure([], (require) => require(`../../../views/${name}${index ? '/index' : ''}.vue`))

文件里面只有這一行代碼,用處是告訴 webpack 在加載 .vue 文件時(shí),知道去哪里找這個(gè)文件,比如
lazyLoading('projects/Projects') 指的是 ../../../views/projects/Projects.vue,也就是 src/views/projects/Proejcts.vue 這個(gè)文件。當(dāng) lazyloading('xxxx', index=true) 時(shí),會(huì)去找 xxxx 文件夾下面的 index.vue。

Vue-router

Vue-router 對(duì)應(yīng)了 src/router/index.js 里的代碼。

import Vue from 'vue'
import Router from 'vue-router'
import menuModule from 'vuex-store/modules/menu'

Vue.use(Router);

export default new Router({
  routes: [
    ...generateRoutesFromMenu(menuModule.state.items),
    {
      path: '*',
      redirect: '/projects'
    }
  ]
})

function generateRoutesFromMenu (menu = [], routes = []) {
  for (let i = 0, l = menu.length; i < l; i++) {
    let item = menu[i];
    if (item.path) {
      routes.push(item)
    }
    if (!item.component) {
      generateRoutesFromMenu(item.subItems, routes)
    }
  }
  return routes
}

將應(yīng)用的所有路徑都定義在

new Router({
  routes: [
   ......
  ]
})

generateRoutesFromMenu 這個(gè)函數(shù)的作用是將定義在 src/store/modules/menu 里的每個(gè)目錄里包含了 component 的加載進(jìn)應(yīng)用的路由里,path 對(duì)應(yīng)的是路徑,component 是指向哪個(gè) .vue 文件,比如 Vuex 那個(gè)例子,訪問 host:port/projects 這個(gè)頁面,應(yīng)用會(huì)加載 src/views/projects/Project.vue。

{
  path: '*',
  redirect: '/projects'
}

這個(gè)的作用是用戶訪問任何沒有定義的路徑時(shí),自動(dòng)重新載入到 host:port/projects 這個(gè)頁面,正??梢詫懸粋€(gè)錯(cuò)誤頁面。

到這邊就簡單的介紹了如何使用 Vuetify, Vuex, Vue-router,最后在 src/main.js 里,加載 store 和 router,放到 new Vue() 里就可以了

new Vue({
  el: '#app',
  router,
  store,
  template: '<App/>',
  components: { App }
});

一篇文章能介紹的內(nèi)容實(shí)在有限,只是比較大概的介紹了整體各個(gè)模塊怎么結(jié)合,還有許多細(xì)節(jié)需要參考文檔,已經(jīng)在寫代碼的過程中去排雷,權(quán)當(dāng)一個(gè)拋磚引玉了。

大家有碰到什么這方面的問題可以留言,一定盡力解答。一些文檔附錄在下面,供大家參考。

Vue: https://vuejs.org/
Vuetify: https://vuetifyjs.com/
Vuex: https://vuex.vuejs.org/
Vue-router: https://router.vuejs.org/
Vue-router-sync: https://github.com/vuejs/vuex-router-sync

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容