>  기사  >  웹 프론트엔드  >  node+vue.js를 사용하여 SPA 애플리케이션 구현

node+vue.js를 사용하여 SPA 애플리케이션 구현

高洛峰
高洛峰원래의
2017-01-03 17:16:001262검색

비즈니스 요구사항

최근 회사에서 웹 버전의 앱 개발을 요구하고 있습니다. 앱이 콘텐츠 중심이고 채팅 모듈이 있기 때문에 일반적인 다중 페이지 개발은 그다지 적합하지 않으며, 주로 모바일 브라우징용입니다. 로딩 속도나 사용자 경험 측면에서 더 까다롭습니다. 많은 프레임워크와 모델을 연구한 끝에 마침내 이와 같은 것을 만들었습니다.

서버측

노드를 사용하고, 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(&#39;vueServer.htmlReady&#39;, function(html:string) {
    //这里用的是ejs模板 可以把需要用到的数据设置成window下的全局变量,方便客户端的js访问。
    res.render(&#39;layout&#39;,{server_html:html,server_data:&#39;window.cm_data = {name:"张三"}&#39;})
  });
 
};
#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: &#39;/foo&#39; }">Go to Foo</a>
    <a v-link="{ path: &#39;/bar&#39; }">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 &#39;./vue.min&#39; //客户端的vue.js
import VueRouter from &#39;./vue-router.min&#39; //vue的路由插件,配合webpack可以很简单实现懒加载
 
//懒加载路由 只有访问这个路由才会加载js
import Foo from &#39;bundle?lazy!../../components/foo&#39; //配合webpack的bundle-loader,轻松实现懒加载
import Bar from &#39;bundle?lazy!../../components/bar&#39;
import Index from &#39;bundle?lazy!../../components/index&#39;
 
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({
  &#39;/&#39;  : {
    component: Index //前端路由定义,
  },
  &#39;/foo&#39;: {
    component: Foo
  },
  &#39;/bar&#39;: {
    component: Bar
  }
})
 
//启动APP
router.start(App, &#39;#app&#39;)

개선이 필요한 부분

통합전선 -end 및 back-end 템플릿을 사용하여 html을 분리하는 방법을 찾았습니다. 노드 측은 fs.readFileSync 메서드를 사용하여 이를 얻고, 클라이언트 측은 webpack의 raw-loader를 사용하여 html 콘텐츠를 얻습니다

node+vue.js를 사용하여 SPA 애플리케이션을 구현하는 방법에 대한 더 많은 관련 기사를 보려면 PHP 중국어 웹사이트를 팔로우하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.