从零构建vue2 + vue-router + vuex 开发环境到入门,实现基本的登录退出功能(二)
发布于 9 年前 作者 1340641314 10444 次浏览 来自 分享

前言

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

github:https://github.com/lzxb/vue2-demo

源码说明

项目目录说明

.
|-- 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的完整项目,
可以使用最简单的方式实现页面后台时状态还原,
局部滚动条还原等。
1 回复
回到顶部

AltStyle によって変換されたページ (->オリジナル) /