UDN-企业互联网技术人气社区

板块导航

浏览  : 585
回复  : 2

[原生js] 使用node+vue.js实现SPA应用

[复制链接]
牛娜的头像 楼主
发表于 2017-1-8 14:34:45 | 显示全部楼层 |阅读模式
  这篇文章主要介绍了使用node+vue.js实现SPA应用的相关资料,需要的朋友可以参考下

  业务需求
  
  最近公司要求开发web版的app,由于app是偏向内容方面,而且带了一个聊天模块,所以一般的多页开发不是很适合,而且主要是手机浏览,对加载速度或者用户体验来说都比较苛刻。调研了很多框架和模式,最后自己东拼西凑搞出来了这么一个玩意。
  
  服务端
  
  毫无疑问使用node,使用typescript可以有效的在编码同时查错,强类型语言写服务端毫无压力。
  1. #app.ts 只贴重要代码

  2. var webpack = require('webpack')
  3. var webpackDevMiddleware = require('webpack-dev-middleware')
  4. var WebpackConfig = require('./webpack.config')

  5. import * as index from "./routes/index";
  6. import * as foo from "./routes/foo";
  7. import * as bar from "./routes/bar";

  8. var app = express();

  9. //启动服务的时候 打包并监听客户端用到的文件,webpackDevMiddleware是开发模式,他会打包js在内存里面,你改了文件,它也会重新打包
  10. app.use(webpackDevMiddleware(webpack(WebpackConfig), {
  11.   publicPath: '/__build__/',
  12.   stats: {
  13.     colors: true
  14.   }
  15. }));

  16. //一般的配置项
  17. app.set('views', __dirname + '/views');
  18. app.set('view engine', 'ejs');
  19. app.set('view options', { layout: false });
  20. app.use(bodyParser.urlencoded({ extended: true }));
  21. app.use(bodyParser.json());
  22. app.use(methodOverride());
  23. app.use(express.static(__dirname + '/public'));

  24. var env = process.env.NODE_ENV || 'development';
  25. if (env === 'development') {
  26.   app.use(errorHandler());
  27. }

  28. //路由配置
  29. app.get('/', index.index);
  30. app.get('/foo', foo.index);
  31. app.get('/bar', bar.index);


  32. app.listen(3000, function(){
  33.   console.log("Demo Express server listening on port %d in %s mode", 3000, app.settings.env);
  34. });

  35. export var App = app;
复制代码

  服务端渲染页面
  1. #index.ts
  2. import express = require("express")
  3. import vueServer = require("vue-server") //服务端渲染vue的插件

  4. var Vue = new vueServer.renderer(); //创建一个服务端的vue

  5. export function index(req: express.Request, res: express.Response) {

  6.   //创建一个组件
  7.   var vm = new Vue({
  8.     template: `
  9.     <p>This is index!</p>
  10.     `
  11.   });

  12.   //等待html渲染完成,再返回给浏览器 vueServer.htmlReady是vue-server的自带事件
  13.   vm.$on('vueServer.htmlReady', function(html:string) {
  14.     //这里用的是ejs模板 可以把需要用到的数据设置成window下的全局变量,方便客户端的js访问。
  15.     res.render('layout',{server_html:html,server_data:'window.cm_data = {name:"张三"}'})
  16.   });

  17. };
复制代码
  1. #layout.ejs 访问这个SPA的所有url返回的都是这个页面 <meta>标签都可以动态设置,只要传参数进来就可以
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5.   <meta charset="utf-8">
  6.   <title>Vue Router Example</title>
  7.   <style>
  8.     .v-link-active {
  9.       color: red;
  10.     }
  11.   </style>
  12.   <script>
  13.     //定义一些前端需要用到的全局属性,文章ID或用户信息什么的
  14.     //index.ts中传过来的是 window.cm_data = {name:"张三"}
  15.     //前端就能访问到了
  16.     <%-server_data%>
  17.   </script>
  18. </head>
  19. <body>

  20. //这里的id是前端需要用到的一个标识
  21. <div id="app">
  22.   <h1>Hello App!</h1>
  23.   <p>
  24.     <a v-link="{ path: '/foo' }">Go to Foo</a>
  25.     <a v-link="{ path: '/bar' }">Go to Bar</a>
  26.   </p>
  27.   //router-view是客户端vue-router需要解析的dom
  28.   //server_html是根据访问url地址生成的html,是做SEO的重点,不加载下面的app.js也可以看到内容
  29.   <router-view> <%-server_html%> </router-view>
  30. </div>
  31. //webpack打包好的js,主要是路由配置
  32. <script src="/__build__/app.js"></script>
  33. </body>
  34. </html>
复制代码

  客户端
  1. #app.js 这个是/__build__/app.js,可以用es6编写,webpack会转换的

  2. import Vue from './vue.min' //客户端的vue.js
  3. import VueRouter from './vue-router.min' //vue的路由插件,配合webpack可以很简单实现懒加载

  4. //懒加载路由 只有访问这个路由才会加载js
  5. import Foo from 'bundle?lazy!../../components/foo' //配合webpack的bundle-loader,轻松实现懒加载
  6. import Bar from 'bundle?lazy!../../components/bar'
  7. import Index from 'bundle?lazy!../../components/index'

  8. var App = Vue.extend({})

  9. Vue.use(VueRouter)

  10. var router = new VueRouter({
  11.   //这里要好好说一下,一定要设置html5模式,不然前后端URL不统一会发生问题
  12.   //比如访问 http://localhost:3000/ 服务端定义是访问index.ts这个路由文件
  13.   //如果不是html5模式的话,经过客户端js运行之后会变成http://localhost:3000/#!/
  14.   
  15.   //在比如直接浏览器输入 http://localhost:3000/foo 服务端定义是访问.ts这个路由文件
  16.   //如果不是html5模式的话,经过客户端js运行之后会变成 http://localhost:3000/foo/#!/
  17.   
  18.   //设置了html5模式后,加载完js后不会加上#!这2个类似锚点的字符,实现前后端路由统一如果用户刷新浏览器的话,服务端也能渲染出相应的页面。
  19.   history: true, //html5模式 去掉锚点
  20.   saveScrollPosition: true //记住页面的滚动位置 html5模式适用
  21. })

  22. //定义路由,要和服务端路由路径定义的一样
  23. router.map({
  24.   '/'  : {
  25.     component: Index //前端路由定义,
  26.   },
  27.   '/foo': {
  28.     component: Foo
  29.   },
  30.   '/bar': {
  31.     component: Bar
  32.   }
  33. })

  34. //启动APP
  35. router.start(App, '#app')
复制代码
 

     需要完善的地方

  前后端统一模板,已经找到方法了把html分离出来,node端用fs.readFileSync方法获取,客户端用webpack的raw-loader获取html内容
  
  不放源码都是瞎扯。
  
  源码地址
  
  https://github.com/yjj5855/node-vue-server-webpack
发表于 2017-1-8 14:35:14 | 显示全部楼层
占坑编辑ing
使用道具 举报

回复

发表于 2017-1-8 14:35:15 来自手机 | 显示全部楼层
个人觉得js是一种解释性语言,它提供了一个非常方便的开发过程,不需要编译,js与HTML标识结合在一起,从而方便用户的使用操作。
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部