从零构建vue2 + vue-router + vuex 开发环境到入门,实现基本的登陆退出功能(二)

前言

国庆在回家的路上,得知了vue2发布了正式版,
国庆回来后,在公司内两个项目便直接应用上了vue2,
一个是PC端的商户后台,一个是微信端商城,
都是基于Vue二、vue-router、vuex ......
在开发的过程当中,遇到了一系列的问题,
好比页面后退数据还原,滚动条还原,
登陆超时,获取列表数据,表单提交,
多台服务器自动化部署,最终后一个个解决了,
可以平稳的从react切换到vue2开发,vue的文档功不可没。复制代码

github:github.com/lzxb/vue2-d…javascript

源码说明

项目目录说明

.
|-- config                           // 项目开发环境配置
|   |-- index.js                     // 项目打包部署配置
|-- src                              // 源码目录
|   |-- components                   // 公共组件
|       |-- header.vue               // 页面头部公共组件
|       |-- index.js                 // 加载各类公共组件
|   |-- config                       // 路由配置和程序的基本信息配置
|       |-- routes.js                // 配置页面路由
|   |-- css                          // 各类css文件
|       |-- common.css               // 全局通用css文件
|   |-- iconfont                     // 各类字体图标
|   |-- images                       // 公共图片
|   |-- less                         // 各类less文件
|       |-- common.less              // 全局通用less文件
|   |-- pages                        // 页面组件
|       |-- home                     // 我的中心
|       |-- index                    // 网站首页
|       |-- login                    // 登陆
|       |-- signout                  // 退出
|   |-- store                        // vuex的状态管理
|       |-- index.js                 // 加载各类store模块
|       |-- user.js                  // 用户store
|   |-- template                     // 各类html文件
|       |-- index.html               // 程序入口html文件
|   |-- util                         // 公共的js方法,vue的mixin混合
|   |-- app.vue                      // 页面入口文件
|   |-- main.js                      // 程序入口文件,加载各类公共组件
|-- .babelrc                         // ES6语法编译配置
|-- gulpfile.js                      // 启动,打包,部署,自动化构建
|-- webpack.config.js                // 程序打包配置
|-- server.js                        // 代理服务器配置
|-- README.md                        // 项目说明
|-- package.json                     // 配置项目相关信息,经过执行 npm init 命令建立
.复制代码

1.html入口文件,源文件路径:src/template/index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,minimal-ui">
    <title>vue2-demo</title>
</head>

<body>
    <div id="app">
        <router-view></router-view>
    </div>
</body>

</html>复制代码

2.js入口文件,源文件路径:src/main.js

import Vue from 'vue'
import VueRouter from 'vue-router'

import routes from './config/routes'
import store from './store/'
import components from './components/' //加载公共组件

import './css/common.css'
import './less/common.less'

Object.keys(components).forEach((key) => {
    var name = key.replace(/(\w)/, (v) => v.toUpperCase()) //首字母大写
    Vue.component(`v${name}`, components[key])
})

Vue.use(VueRouter)

const router = new VueRouter({
    routes
})
router.beforeEach(({meta, path}, from, next) => {
    var { auth = true } = meta
    var isLogin = Boolean(store.state.user.id) //true用户已登陆, false用户未登陆

    if (auth && !isLogin && path !== '/login') {
        return next({ path: '/login' })
    }
    next()
})

new Vue({ store, router }).$mount('#app')复制代码

3.页面路由,权限配置,源文件路径:src/config/routes.js

import App from '../app'

export default [
    {
        path: '/',
        component: App,
        children: [
            {
                path: '/login', //登陆
                meta: { auth: false },
                component: resolve => require(['../pages/login/'], resolve)
            },
            {
                path: '/signout', //退出
                component: resolve => require(['../pages/signout/'], resolve)
            },
            {
                path: '/home', //我的主页
                component: resolve => require(['../pages/home/'], resolve)
            },
            {
                path: '/', //首页
                meta: { auth: false },
                component: resolve => require(['../pages/index/'], resolve)
            },
            {
                path: '*', //其余页面,强制跳转到登陆页面
                redirect: '/login'
            }
        ]
    }
]复制代码

4.页面入口组件,源文件路径:src/app.vue

<style lang="less" scoped> </style>
<template>
    <router-view></router-view>
</template>
<script> export default { } </script>复制代码

5.store实例化,导入各类modules,源文件路径:src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import user from './user'

Vue.use(Vuex)

export default new Vuex.Store({
    strict: process.env.NODE_ENV !== 'production', //在非生产环境下,使用严格模式
    modules: {
        user
    }
})复制代码

6.定义store user 模块,源文件路径:src/store/user.js

import Vue from 'vue'

export const USER_SIGNIN = 'USER_SIGNIN' //登陆成功
export const USER_SIGNOUT = 'USER_SIGNOUT' //退出登陆

export default {
    state: JSON.parse(sessionStorage.getItem('user')) || {},
    mutations: {
        [USER_SIGNIN](state, user) {
            sessionStorage.setItem('user', JSON.stringify(user))
            Object.assign(state, user)
        },
        [USER_SIGNOUT](state) {
            sessionStorage.removeItem('user')
            Object.keys(state).forEach(k => Vue.delete(state, k))
        }
    },
    actions: {
        [USER_SIGNIN]({commit}, user) {
            commit(USER_SIGNIN, user)
        },
        [USER_SIGNOUT]({commit}) {
            commit(USER_SIGNOUT)
        }
    }
}复制代码

7.加载各类公共组件,源文件路径:src/components/index.js

import header from './header'
export default { header }复制代码

8.封装页面公共头部组件,源文件路径:src/components/header.js

<style lang="less" scoped> .header { position: relative; line-height: 38px; color: #fff; text-align: center; background: #222; .item { position: absolute; top: 0; bottom: 0; z-index: 1; a { color: #fff; } } .left { left: 10px; } .right { right: 10px; } } </style>
<template>
    <header class="header">
        <div class="item left">
            <slot name="left"></slot>
        </div>
        <div class="title">{{title}}</div>
        <div class="item right">
            <slot name="right"></slot>
        </div>
    </header>
</template>
<script> export default { props: { title: { type: String, default: '' } } } </script>复制代码

9.引入全局公共css,源文件路径:src/css/common.css

input::-webkit-outer-spin-button,  
input::-webkit-inner-spin-button{  
    -webkit-appearance: none !important;  
    margin: 0;  
}复制代码

10.引入全局公共less,源文件路径:src/less/common.less

* {
    padding: 0;
    margin: 0;
}复制代码

11.建立首页,,源文件路径:src/pages/index.vue

<style lang="less" scoped> .login-msg { padding: 50px; text-align: center; } .msg { padding: 50px; text-align: center; font-size: 20px; color: red; } </style>
<template>
    <div>
        <v-header title="首页">
            <router-link slot="right" v-if="user.id" to="/home">{{user.name}}</router-link>
        </v-header>
        <div class="login-msg" v-if="!user.id">
            <router-link to="/login">你还未登陆,请先登陆</router-link>
        </div>
        <div class="msg" v-if="user.id">
            <img width="50" :src="logo" alt=""> <br>
            哈哈,恭喜你已经入坑Vue2
        </div>
    </div>
</template>
<script> import { mapState } from 'vuex' import logo from './logo.png' export default { data() { return { logo } }, computed: mapState({ user: state => state.user }), } </script>复制代码

12.建立登陆页,,源文件路径:src/pages/login.vue

<style lang="less" scoped> .login { padding: 50px; text-align: center; .line { padding: 5px; input { padding: 0 10px; line-height: 28px; } } button { padding: 0 20px; margin-top: 20px; line-height: 28px; } } </style>
<template>
    <div>
        <v-header title="登陆">
            <router-link slot="left" to="/">返回</router-link>
        </v-header>
        <form class="login" v-on:submit.prevent="submit">
            <div class="line">    
                <div v-show="btn && !form.id">id不能为空</div>
                <input type="number" placeholder="输入你的id" v-model="form.id">
            </div>
            <div class="line">
                <div v-show="btn && !form.name">用户名不能为空</div>
                <input type="text" placeholder="输入你的用户名" v-model="form.name">
            </div>
            <button>登陆</button>
        </form>
    </div>
</template>
<script> import { mapActions } from 'vuex' import { USER_SIGNIN } from 'store/user' export default { data() { return { btn: false, //true 已经提交过, false没有提交过 form: { id: '', name: '' } } }, methods: { ...mapActions([USER_SIGNIN]), submit() { this.btn = true if(!this.form.id || !this.form.name) return this.USER_SIGNIN(this.form) this.$router.replace({ path: '/home' }) } } } </script>复制代码

13.建立我的主页,,源文件路径:src/pages/home.vue

<style lang="less" scoped> </style>
<template>
    <div>
        <v-header title="首页">
            <router-link slot="left" to="/">首页</router-link>
            <router-link slot="right" to="/signout">退出</router-link>
        </v-header>
        <div style="padding: 50px;">{{user.name}}欢迎回家</div>
    </div>
</template>
<script> import { mapState } from 'vuex' export default { computed: mapState({ user: state => state.user }), } </script>复制代码

14.建立退出页,,源文件路径:src/pages/signout.vue

<style lang="less" scoped> .btn { padding: 50px; text-align: center; button { padding: 5px 10px; } } </style>
<template>
    <div>
        <v-header title="退出">
            <router-link slot="left" to="/home">返回</router-link>
        </v-header>
        <div class="btn">
            <button v-on:click="submit">确认退出</button>
        </div>
    </div>
</template>
<script> import { mapActions } from 'vuex' import { USER_SIGNOUT } from 'store/user' export default { methods: { ...mapActions([USER_SIGNOUT]), submit() { this.USER_SIGNOUT() this.$router.replace({ path: '/login' }) } } } </script>复制代码

进击vue2

vue2重构cnode社区,将会近日完成,
一个从0构建的vue2的完整项目,
能够使用最简单的方式实现页面后退时状态还原,
局部滚动条还原等。复制代码
相关文章
相关标签/搜索