视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
使用node+vue.js实现SPA应用
2020-11-27 20:27:13 责编:小采
文档

业务需求

最近公司要求开发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:"张三"}'})
 });
 
};
#layout.ejs 访问这个SPA的所有url返回的都是这个页面 <meta>标签都可以动态设置,只要传参数进来就可以
<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title>Vue Router Example</title>
 <style>
 .v-link-active {
 color: red;
 }
 </style>
 <script>
 //定义一些前端需要用到的全局属性,文章ID或用户信息什么的
 //index.ts中传过来的是 window.cm_data = {name:"张三"}
 //前端就能访问到了
 <%-server_data%>
 </script>
</head>
<body>
 
//这里的id是前端需要用到的一个标识
<div id="app">
 <h1>Hello App!</h1>
 <p>
 <a v-link="{ path: '/foo' }">Go to Foo</a>
 <a v-link="{ path: '/bar' }">Go to Bar</a>
 </p>
 //router-view是客户端vue-router需要解析的dom
 //server_html是根据访问url地址生成的html,是做SEO的重点,不加载下面的app.js也可以看到内容
 <router-view> <%-server_html%> </router-view>
</div>
//webpack打包好的js,主要是路由配置
<script src="/__build__/app.js"></script>
</body>
</html>

客户端

#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内容

更多使用node+vue.js实现SPA应用相关文章请关注PHP中文网!

下载本文
显示全文
专题