这篇文章主要介绍了使用 node+vue.js 实现 SPA 应用的相关资料, 需要的朋友可以参考下
Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台, 用来方便地搭建快速的 易于扩展的网络应用 · Node.js 借助事件驱动, 非阻塞 I/O 模型变得轻量和高效, 非常适合 运行在分布式设备 的 数据密集型 的实时应用
业务需求
最近公司要求开发 web 版的 app, 由于 app 是偏向内容方面,而且带了一个聊天模块,所以一般的多页开发不是很适合,而且主要是手机浏览,对加载速度或者用户体验来说都比较苛刻。调研了很多框架和模式,最后自己东拼西凑搞出来了这么一个玩意。
服务端
毫无疑问使用 node,使用 typescript 可以有效的在编码同时查错,强类型语言写服务端毫无压力。
- #app.ts只贴重要代码
- var webpack = require('webpack') var webpackDevMiddleware = require('webpack-dev-middleware') var WebpackConfig = require('./webpack.config') import * as index from "./routes/index";
- import * as foo from "./routes/foo";
- import * as bar from "./routes/bar";
- var app = express();
- //启动服务的时候 打包并监听客户端用到的文件,webpackDevMiddleware是开发模式,他会打包js在内存里面,你改了文件,它也会重新打包
- app.use(webpackDevMiddleware(webpack(WebpackConfig), {
- publicPath: '/__build__/',
- stats: {
- colors: true
- }
- }));
- //一般的配置项
- app.set('views', __dirname + '/views');
- app.set('view engine', 'ejs');
- app.set('view options', {
- layout: false
- });
- app.use(bodyParser.urlencoded({
- extended: true
- }));
- app.use(bodyParser.json());
- app.use(methodOverride());
- app.use(express.static(__dirname + '/public'));
- var env = process.env.NODE_ENV || 'development';
- if (env === 'development') {
- app.use(errorHandler());
- }
- //路由配置
- app.get('/', index.index);
- app.get('/foo', foo.index);
- app.get('/bar', bar.index);
- app.listen(3000,
- function() {
- console.log("Demo Express server listening on port %d in %s mode", 3000, app.settings.env);
- });
- export
- var App = app;
服务端渲染页面
- #index.ts
- import express = require("express")
- import vueServer = require("vue-server") //服务端渲染vue的插件
- var Vue = new vueServer.renderer(); //创建一个服务端的vue
- export function index(req: express.Request, res: express.Response) {
- //创建一个组件
- var vm = new Vue({
- template: `
- <p>This is index!</p>
- `
- });
- //等待html渲染完成,再返回给浏览器 vueServer.htmlReady是vue-server的自带事件
- vm.$on('vueServer.htmlReady', function(html:string) {
- //这里用的是ejs模板 可以把需要用到的数据设置成window下的全局变量,方便客户端的js访问。
- res.render('layout',{server_html:html,server_data:'window.cm_data = {name:"张三"}'})
- });
- };
客户端
- #app.js 这个是/__build__/app.js,可以用es6编写,webpack会转换的
- import Vue from './vue.min' //客户端的vue.js
- import VueRouter from './vue-router.min' //vue的路由插件,配合webpack可以很简单实现懒加载
- //懒加载路由 只有访问这个路由才会加载js
- import Foo from 'bundle?lazy!../../components/foo' //配合webpack的bundle-loader,轻松实现懒加载
- import Bar from 'bundle?lazy!../../components/bar'
- import Index from 'bundle?lazy!../../components/index'
- var App = Vue.extend({})
- Vue.use(VueRouter)
- var router = new VueRouter({
- //这里要好好说一下,一定要设置html5模式,不然前后端URL不统一会发生问题
- //比如访问 http://localhost:3000/ 服务端定义是访问index.ts这个路由文件
- //如果不是html5模式的话,经过客户端js运行之后会变成http://localhost:3000/#!/
- //在比如直接浏览器输入 http://localhost:3000/foo 服务端定义是访问.ts这个路由文件
- //如果不是html5模式的话,经过客户端js运行之后会变成 http://localhost:3000/foo/#!/
- //设置了html5模式后,加载完js后不会加上#!这2个类似锚点的字符,实现前后端路由统一如果用户刷新浏览器的话,服务端也能渲染出相应的页面。
- history: true, //html5模式 去掉锚点
- saveScrollPosition: true //记住页面的滚动位置 html5模式适用
- })
- //定义路由,要和服务端路由路径定义的一样
- router.map({
- '/' : {
- component: Index //前端路由定义,
- },
- '/foo': {
- component: Foo
- },
- '/bar': {
- component: Bar
- }
- })
- //启动APP
- router.start(App, '#app')
需要完善的地方
前后端统一模板, 已经找到方法了把 html 分离出来,node 端用 fs.readFileSync 方法获取,客户端用 webpack 的 raw-loader 获取 html 内容
不放源码都是瞎扯。
源码地址
来源: http://www.phperz.com/article/17/0215/267325.html