Vue 2.0 + Vue Router + Vuex

来源:http://www.cnblogs.com/caihg/archive/2016/12/09/6150158.html
-Advertisement-
Play Games

用 Vue.js 2.x 與相配套的 Vue Router、Vuex 搭建了一個最基本的後臺管理系統的骨架。 當然先要安裝 node.js(包括了 npm)、vue-cli 項目結構如圖所示: assets 中是靜態資源,components 中是組件(以 .vue 為尾碼名的文件),store 中 ...


用 Vue.js 2.x 與相配套的 Vue Router、Vuex 搭建了一個最基本的後臺管理系統的骨架。

當然先要安裝 node.js(包括了 npm)、vue-cli

項目結構如圖所示:

assets 中是靜態資源,components 中是組件(以 .vue 為尾碼名的文件),store 中是使用了 vuex 的 js 文件。

package.json:

{
  "name": "element-starter",
  "description": "A Vue.js project",
  "author": "caihg",
  "private": false,
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --inline --hot --open",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  },
  "dependencies": {
    "element-ui": "^1.0.0",
    "vue": "^2.1.0",
    "vue-router": "^2.1.1",
    "vue-server-renderer": "^2.1.3",
    "vuex": "^2.0.0",
    "vuex-router-sync": "^3.0.0"
  },
  "devDependencies": {
    "babel-core": "^6.0.0",
    "babel-loader": "^6.0.0",
    "babel-preset-es2015": "^6.13.2",
    "cross-env": "^1.0.6",
    "css-loader": "^0.23.1",
    "file-loader": "^0.8.5",
    "style-loader": "^0.13.1",
    "vue-loader": "^10.0.0",
    "vue-template-compiler": "^2.1.0",
    "webpack": "^2.1.0-beta.25",
    "webpack-dev-server": "^2.1.0-beta.0",
    "webpack-dev-middleware": "^1.6.1"
  }
}

webpack.config.js:

var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js'
  },
  module: {
    loaders: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader'
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
        loader: 'file-loader'
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?\S*)?$/,
        loader: 'file-loader',
        query: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  devServer: {
    historyApiFallback: true,
    noInfo: true
  },
  devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ])
}

項目的入口 js 文件 main.js:

import Vue from 'vue'
import VueRouter from 'vue-router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'

Vue.use(VueRouter)
Vue.use(ElementUI)

import routes from './routes'
const router = new VueRouter({
  mode: 'history',
  base: __dirname,
  routes: routes
})

import Main from './components/main.vue'
new Vue({
  el: '#app',
  router,
  render: h => h(Main)
})

該文件引用了路由配置文件 routes.js 和主入口的組件 main.vue,其中 main.vue 在 components 目錄

 

routes.js 內容如下:

import Login from './components/login/login.vue'
import Container from './components/container/container.vue'
import UserHome from './components/container/userHome.vue'
import Platform from './components/asideContainer/platform.vue'
import UserList from './components/platform/userList.vue'
import UserCreate from './components/platform/userCreate.vue'
import Product from './components/asideContainer/product.vue'
import ProductList from './components/product/list.vue'
import ProductBrand from './components/product/brand.vue'
import NotFound from './components/error/notFound.vue'

export default [
  {
    path: '/login',
    component: Login
  },
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/page',
    component: Container,
    children: [
      {
        path: 'userHome',
        component: UserHome
      },
      {
        path: 'platform',
        redirect: 'platform/userList', // 預設指向用戶列表(UserList)
        component: Platform,
        children: [
          {
            path: 'userList',
            component: UserList
          },
          {
            path: 'userCreate',
            component: UserCreate
          }
        ]
      },
      {
        path: 'product',
        redirect: 'product/list', // 預設指向商品列表(ProductList)
        component: Product,
        children: [
          {
            path: 'list',
            component: ProductList
          },
          {
            path: 'brand',
            component: ProductBrand
          }
        ]
      }
    ]
  },
  { // 404頁面:必須位於最後,否則其它的路由地址都會使用 NotFound 組件
    path: '*',
    component: NotFound
  }
]

main.vue 的內容如下:

<template>
  <router-view></router-view>
</template>

 store.js 在 store 目錄,內容如下:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    username: ''
  }
})

 

後臺都是登錄成功後跳轉到主頁面

 

界面的 UI 用的是開源的 element-ui

login.vue 位於 login 目錄,內容如下:

<template>
  <div class="box">
    <el-form :model="loginForm" :rules="loginRules" ref="loginForm" label-width="100px" class="form-box">
      <el-form-item label="用戶名" prop="username">
        <el-input v-model="loginForm.username" placeholder="請輸入用戶名" auto-complete="off"></el-input>
      </el-form-item>
      <el-form-item label="密碼" prop="password">
        <el-input type="password" v-model="loginForm.password" auto-complete="off"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onLogin">登錄</el-button>
        <el-button @click="handleReset">重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import store from '../../store/store'
export default {
  data() {
    var validateUsername = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('請輸入用戶名'));
      } else {
        callback();
      }
    };
    var validatePassword = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('請輸入密碼'));
      } else {
        callback();
      }
    };

    return {
      loginForm: {
        username: '',
        password: ''
      },
      loginRules: {
        username: [
          { validator: validateUsername, trigger: 'blur' }
        ],
        password: [
          { validator: validatePassword, trigger: 'blur' }
        ]
      }
    };
  },
  methods: {
    onLogin(event) {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          store.state.username = this.loginForm.username;
          this.$router.push('page/userHome');
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    handleReset() {
      this.$refs.loginForm.resetFields();
    }
  }
}
</script>

<style>
.form-box {
  width: 500px;
  margin-top: 100px;
  margin-right: auto;
  margin-left: auto;
}
</style>

在登錄事件中,將用戶名傳遞給 store 中的 state.username,以便在其它組件中獲取: 

store.state.username = this.loginForm.username

 

登錄後的界面,預設跳轉到主頁:

 

通過 vuex 獲取到了登錄的用戶名稱(caihg);當然,如果刷新當前頁面,用戶名稱就沒了。 

頭部在 container 目錄,其中有三個組件

container.vue 的內容如下:

<template>
  <div class="container">
    <header-nav></header-nav>
    <router-view></router-view>
  </div>
</template>

<script>
import headerNav from './headerNav.vue'
export default {
  components: {
    headerNav
  }
}
</script>

<style>
header > h1 {
  display: inline-block;
}
header > a {
  margin: 0 10px;
  color: #000;
  text-decoration: none;
}
</style>

headerNav.vue 中就是頭部導航的各種鏈接:

<template>
  <header>
    <h1>管理平臺</h1>
    <router-link to="/page/userHome">主頁</router-link>
    <router-link to="/page/platform">平臺管理</router-link>
    <router-link to="/page/product">商品管理</router-link>
    <strong>歡迎你,{{ getUsername }}</strong>
  </header>
</template>

<script>
import store from '../../store/store'
export default {
  computed: {
    getUsername () {
      return store.state.username
    }
  }
}
</script>

<style>
header > .router-link-active {
  color: red;
}
header > strong {
  padding-left: 50px;
}
</style>

 

點擊頭部的導航,下麵的內容相應地切換

 其中左側部分也是導航,點擊也要跟隨切換

左側的導航放在 asideContainer 目錄

 platform.vue 與 product.vue 內容相似;只是前者包括了樣式,後者沒有(相同的樣式寫一份就夠了,如果多寫了,也會重覆渲染)

<template>
  <!-- 平臺管理 -->
  <div>
    <ul class="aside-nav">
      <li><router-link to="/page/platform/userList">用戶列表</router-link></li>
      <li><router-link to="/page/platform/userCreate">用戶創建</router-link></li>
    </ul>
    <router-view class="aside-container"></router-view>
  </div>
</template>

<style>
.aside-nav {
  float: left;
  width: 100px;
  margin: 0 50px 0 0;
  padding-left: 0;
}
.aside-nav a {
  display: block;
  padding: 4px 0 5px;
  color: #555;
  text-align: center;
  text-decoration: none;
}
.aside-nav .router-link-active {
  color: #fff;
  background-color: orange;
}
.aside-container {
  float: left;
}
</style>
<template>
  <!-- 商品管理 -->
  <div>
    <ul class="aside-nav">
      <li><router-link to="/page/product/list">商品列表</router-link></li>
      <li><router-link to="/page/product/brand">商品品牌</router-link></li>
    </ul>
    <router-view class="aside-container"></router-view>
  </div>
</template>

 

左側導航對應的內容分別在不同的目錄(根據功能劃分)

userList.vue 中的內容如下:

<template>
  <div>
    用戶列表的內容
  </div>
</template>

至此完成,後臺管理系統的大致骨架就是這樣了。

項目代碼在 github 上


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近開始重構一個稍嫌古老的C/S項目,原先採用的技術棧是『WinForm』+『WCF』+『EF』。相對於現在鋪天蓋地的B/S架構來說,看上去似乎和Win95一樣古老,很多新入行的,可能就沒有見過經典的C/S架構的系統。事實上,作為企業信息管理系統,包括ERP/CRM/SCM等,桌面客戶端還是很OK的 ...
  • 記憶體泄露與垃圾回收機制。 1)、記憶體泄露 由於堆中的對象(數據)創建過多, 導致堆中無法存儲,於是出現了記憶體泄露現象。 此現象非常可怕,後果非常嚴重。需杜絕。 記憶體中存儲的數據為臨時數據,臨時數據使用之後, 要及時清理,使用之後的數據,就變成了“垃圾數據”, Java有對獨立運行的線程,可以實現不定 ...
  • 一、陰影 1.1、文字陰影 text-shadow<length>①: 第1個長度值用來設置對象的陰影水平偏移值。可以為負值 <length>②: 第2個長度值用來設置對象的陰影垂直偏移值。可以為負值 <length>③: 如果提供了第3個長度值則用來設置對象的陰影模糊值。不允許負值 <color> ...
  • 用原生的javascript實現方格拼圖效果 1.新建文件夾 代碼如下: 01.html 01.js 01.css 圖片 遇到一個問題: 在js代碼中的第9行和第10行,本來是一條語句,但我直接用鍵盤迴車把它們分成兩行時,會出現錯誤: 錯誤:syntaxerror:未結束的字元串。 Google之後 ...
  • 一、web font web font是應用在web中的一種字體技術,在CSS中使用font-face定義新的字體。先瞭解操作系統中的字體: a)、安裝好操作系統後,會預設安裝一些字體,這些字體文件描述了每一個文字的形態,一般中文文件大,英文文件小,因為中文字元數多;在控制面板中可以找到文字文件夾, ...
  • img標簽使用絕對路徑無法顯示圖片? 如果這張圖片屬於伺服器圖片或者網路圖片,我們必須在Img標簽里使用網路路徑,只有網路路徑才可以通過瀏覽器發送請求,下載該圖片到用戶的瀏覽器臨時路徑中,才可以顯示在頁面上; 如果這樣圖片在你本地,那麼你可以直接使用該圖片的磁碟路徑展示。 ...
  • Javascript 之探索this的奧秘 前言: this 是 JavaScript 比較特殊的關鍵字,運用的地方之廣,方式之靈活奠定了它的強大,但同時註定了它的難用 。自己剛開始學的時候被繞的很暈,為了徹底弄懂它查了很多資料。然後將自己學的東西整理了一下,以通俗易懂的方式表達出來,權當做學習筆記 ...
  • 公司 部門 姓名 職位 分享內容 痛客夢工廠科技有限公司 技術部 張應欽 Web前端開發工程師 HTML5與CSS3 註:此帖子詳見本人博客文件HTML5與CSS3.docx文件 一、 HTML5 二、 CSS3 三、 jQuery與CSS3選擇器(詳見PDF文檔) 註:部分實例見分享會文件demo ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...