vue+vuex构建单页应用
基本

项目结构
基本目录结构

api:封装与后端接口交互的操作common:放置一些reset.css之类的components:组件entry:项目入口文件index.js,index.css,index.htmlfilters:过滤器。注:虽然vue2.0已经基本废弃(只保留了对文本的过滤)了Vue.filter的用法,此目录下的方法仍然可用于官方推荐用来替代过滤器的计算属性的计算中mixins:一些通用类的混入部分。比如全选、多选可抽出通用的list-togglemock:本地开发的mock数据utils:封装的工具,如对上传文件、日期处理等的封装views:单页应用的视图(视图也是组件,也可放到components中,但个人觉得放在这里比较一目了然)vuex:放置store,actions,mutations,statefis-conf.js:用于测试环境联调时fis实时将前端资源推送到开发机上
如果有自定义指令,还可以加上 directives 目录( vue 的几个可扩展的地方都可以单独做一个目录)。对于项目目录,也可以使用官方提供的另一个工具 vue-cli 来生成,它还会自动构建单元测试( unit )和端对端测试( e2e )的目录和简单示例。
基础组件
vue 除了双向绑定外的一个最大特点就是提供了强大的组件树系统,组件化也是 web 发展的趋势.
每一个 Vue 实例就是一个组件,构造一个组件的也很简单:
var myComponent = Vue.extend({
template: '',
...
})
// 全局注册组件,tag 为 my-component
Vue.component('my-component', MyComponent)
更推荐的做法是写成 *.vue 形式的单文件组件,搭配 vue-loader 使用(下图来自官方文档)。

更多关于组件的内容,见官方文档 组件 。
另外,在使用单文件组件时,样式会被打包到 js 中并在运行时会以 <style> 节点的形式插入到 <head> 里面。此时如果想将组件的样式打包到输出的 css 文件中,只需要在 webpack.config.js 的 module.exports 中加上以下配置即可:
vue: {
loaders: {
js: 'babel-loader?presets[]=es2015&plugins[]=transform-runtime&comments=false',
css:ExtractTextPlugin.extract(['css-loader'])
}
}
刚开始一个项目时,如果在有自己特定的 UI 设计风格,可能需要单独封装一些 textinput,checkbox,radio 等基础组件;如果没有的话(如普通的后台管理系统),也可以使用 Google Material Design ,已经有对应的实现 material-design-lite 。并且 vue 社区中也已经有针对它的 vue组件封装 vue-mdl 。
应用骨架
以“xx管理后台”为例,首先分为上(导航)下(主体内容)两部分,基本结构为:

接下来在 views 里面心间 user.vue ,作为用户管理模块入口,如果每个模块还需要包含二级导航(通常是在页面左侧部分), user.vue 可以像这样:

这两个文件中用到的 router-view ,都是 vue 官方路由插件 vue-router 提供的。
然后是配置单页应用的路由:

在对应的视图组件中,通过route选项的钩子函数,来确定时图在出现和消失的过程中需要执行的行为。更多路由相关,见 官方文档 。
这样,一个基本的:上 -> [左|右]的单页应用骨架就有了。(其他类型的应用也可依此类推)
应用状态管理
应用组件化之后,就需要解决组件之间的通信问题。针对组件之间的通信问题, vue 提供了三种方式: props 属性传递,直接通过引用调用组件方法,自定义事件通信,通过 v-ref (在 vue2.0 已简化为 ref )来建立子组件索引从而调用子组件方法。
porps:基于属性传递,vue提供了单次绑定、单向绑定和双向绑定。(虽然双向绑定在vue2.0中已经废弃)通过引用:子组件可以用
this.$parent访问它的父组件。根实例的后代可以用this.$root访问它。父组件有一个数组this.$children,包含它所有的子元素。通过自定义事件通信:每个
Vue实例都是一个事件触发器:使用
$on()监听事件使用
$emit()在它上面触发事件使用
$dispatch()派发事件,事件沿着父链冒泡(vue2.0已废弃)使用
$broadcast()广播事件,事件向下传导给所有的后代(vue2.0已废弃)在
vue2.0中,可以单独使用一个Vue实例来来担任eventBus的作用。
除了这几种方式,当应用比较复杂时,官方推荐使用另一个官方插件 vuex
类似于 react 的 redux , vue 的 vuex 的 store 也包含一个全局的状态树 state ;修改 state 的行为 mutations (对应 redux 的 actions );执行修改的动作 actions (对应 redux的 createAction )。

以全局 alert 组件的状态为例:
创建
state
export default {
alert: {
show: false,
type: 'alert',
message: '',
onSure: null,
onClose: null
}
}
创建
mutations
export default {
SHOW_ALERT (state, data) {
data.show = true
state.alert = data
},
HIDE_ALERT (state) {
state.alert.show = false
}
}
创建
actions
/*主页面涉及到的actions*/
let noop = () => {}
/*显示浮层alert*/
export const showAlert = ({dispatch}, message = '') => {
if(!message) {
return false
}
dispatch('SHOW_ALERT', {
type: 'alert',
message: message,
onClose: noop
})
}
/*显示浮层confirm*/
export const showConfirm = ({dispatch}, data = {}) => {
if(!data.message) {
return false
}
data.type = 'confirm'
if(typeof data.onClose != 'function') {
data.onClose = noop
}
if(typeof data.onConfirm != 'function') {
data.onConfirm = noop
}
dispatch('SHOW_ALERT', data)
}
/*隐藏浮层*/
export const hideAlert = ({dispatch}) => dispatch('HIDE_ALERT')
构建
store
import Vue from 'vue'
import Vuex from 'vuex'
import actions from './actions'
import mutations from './mutations'
import state from "./state"
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
Vue.config.debug = debug
export default new Vuex.Store({
state,
mutations,
actions,
strict: debug
})
然后在应用的根组件中,通过以下方式获取 vuex 的功能:
/*引入vuex*/
import store from "../vuex/store"
let App = Vue.extend({
store,
components: {
'admin-header': adminHeader,
'alert': alert
}
})
然后再在自组件中的vuex模块通过以下方式获取状态以及触发状态改变的动作:

应用的数据交互
api层
记得之前看过民工叔叔(徐飞)的某篇文章里说的,数据层能够跟UI层分离,这样即使 UI 底层库更换了,也可以使用数据层。同理如果想要对api交互进行替换(如想把某些 ajax 库换成浏览器支持的 fetch api ),也可以直接在这一层进行更改。
mock数据
在开发阶段,有时需要mock一些数据来测试应用。推荐一个对 restful api 友好的第三方工具 json-server 。

index.js
var users = require('./database/users')
module.exports = function() {
return {
"users": users
}
}
database/users.js
module.exports = {
"users": [
{
"user_id": "233",
"user_name": "哈哈哈",
},
{
"user_id": "233",
"user_name": "哈哈哈",
}
],
"more": true,
"result": "SUCCESS"
}
然后终端执行 json-server mock/index.js -port 9999 就开启了一个 restful 的服务了。(也可以把这句写到 npm script 中)
接下来还差一步,就是需要用到 webpack-dev-server 的 proxy 配置:

这样,所有访问 /rest/* 的接口都会被代理到 json-server 的服务上.
应用测试
一个完整的应用应该还具备单元测试、端对端测试等。目前比较成熟的测试框架社区中也有不少,但由于还没油深入研究过,此处不展开。
总结
文章主要是从搭建一款单页应用的整体架构上来进行描述,可能有一些地方不是那么详细,以后有时间在针对单独某些模块再详细描述吧。。
顺便安利一发开源的两个 vue 组件,欢迎拍砖:
vue+vuex构建单页应用的更多相关文章
- 使用 Vuex + Vue.js 构建单页应用
鉴于该篇文章阅读量大,回复的同学也挺多的,特地抽空写了一篇 vue2.0 下的 vuex 使用方法,传送门:使用 Vuex + Vue.js 构建单页应用[新篇] ------------------ ...
- 使用 Vuex + Vue.js 构建单页应用【新篇】
使用 Vuex + Vue.js 构建单页应用[新篇] 在去年的七月六号的时候,发布了一篇 使用 Vuex + Vue.js 构建单页应用 的文章,文章主要是介绍 vuex 的基本使用方法,发现对大部 ...
- 用vuex构建单页
原文地址:点我 前言:在最近学习 Vue.js 的时候,看到国外一篇讲述了如何使用 Vue.js 和 Vuex 来构建一个简单笔记的单页应用的文章.感觉收获挺多,自己在它的例子的基础上进行了一些优化和 ...
- 基于VUE的SPA单页应用开发-加载性能篇
1.基于异步数据的vue页面刷新 先看看基于异步数据的vue页面刷新后,都发生了啥- 如图所示: 图1 基于异步数据的vue页面刷新 网络请求图 步骤如下: step1:请求页面: step2:请求页 ...
- vue2.0 构建单页应用最佳实战
vue2.0 构建单页应用最佳实战 前言 我们将会选择使用一些 vue 周边的库vue-cli, vue-router,vue-resource,vuex 1.使用 vue-cli 创建项目2.使 ...
- React构建单页应用方法与实例
React作为目前最流行的前端框架之一,其受欢迎程度不容小觑,从这门框架上我们可以学到许多其他前端框架所缺失的东西,也是其创新性所在的地方,比如虚拟DOM.JSX等.那么接下来我们就来学习一下这门框架 ...
- 借助 Vue 来构建单页面应用
原文: https://github.com/MeCKodo/vue-tutorial 主题 Vue.js (1/2)Vue构建单页应用最佳实战 前言 我们将会选择使用一些vue周边的库 1.使用no ...
- Nodejs in Visual Studio Code 12.构建单页应用Scrat实践
1.开始 随着前端工程化深入研究,前端工程师现在碉堡了,甚至搞了个自己的前端网站http://div.io/需要邀请码才能注册,不过里面的技术确实牛.距离顶级的前端架构,目前博主应该是far away ...
- 通过Web Api 和 Angular.js 构建单页面的web 程序
通过Web Api 和 Angular.js 构建单页面的web 程序 在传统的web 应用程序中,浏览器端通过向服务器端发送请求,然后服务器端根据这个请求发送HTML到浏览器,这个响应将会影响整个的 ...
随机推荐
- codevs——1576 最长严格上升子序列(序列DP)
时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 给一个数组a1, a2 ... an,找到最长的上升降子序列 ...
- CSS:水平居中与垂直居中
CSS居中算是一个比较基础的问题,在实际运用中,需要考虑到的一般是两种情况,一种是主要是表现为文字,图片等行内元素的居中,一种是指 div 等块级标签元素的居中. 水平居中 1.行内元素 行内元素(主 ...
- Mac下ll、l、la、等简写命令不能使用
Mac默认用的也是Unix系统,Unix系统本身是没有这些简写命令的,可以通过给命令设置别名来使得可以使用这些简写命令 查看本机所有已经设置的命令别名:alias 设置命令别名:alias ll='l ...
- linux 项目管理、服务器管理、服务器维护
代码打包:tar -zcvf ImOra.3.2.6.tgz --exclude=Public/.htaccess --exclude=Apps/Demo Apps/ Config/ Shell/ L ...
- Java分布式服务框架Dubbo初探(待实践)
Dubbo是什么? Dubbo[]是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案. 其核心部分包含: 远程通讯: 提供对多种基于长连接的NIO框架抽象封 ...
- freemarker中include与import的区别
在inc1.ftl与inc2.ftl中的内容分别是: <#assign username="刘德华">与<#assign username="张学友&q ...
- java基础篇3之反射
1.反射的基础 反射的基石---->Class类 java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class 获取字节码对应的实例对象(Class类型) class ...
- Hadoop部署启动异常问题排查
hadoop的日志目录(/home/hadoop/app/hadoop-2.6.4/logs) 1.hadoop启动不正常用浏览器访问namenode的50070端口,不正常,需要诊断问题出在哪里: ...
- 理解支持向量机(三)SMO算法
在支持向量机模型的求解中,我们用到了SMO算法来求解向量α. 那么什么是SMO算法?在讲SMO算法之前.我们须要先了解下面坐标上升法. 1.坐标上升法 如果有优化问题: W是α向量的函数.利用坐标上升 ...
- mysql报错1872: Slave failed to initialize relay log info structure from the repository
ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository 在一台主机上增加 ...