如果想看该实战系列的其他内容,请移步至 Vue.js 实战系列之实现视频类WebApp的项目开发。
项目仓库地址,欢迎 Star
代码结构优化
-
公共组件的提取封装
目前比较流行组件化开发,组件化开发的好处:方便我们在各个不同的项目中复用代码。当然,我们在项目开发中也一直不断的封装组件来使用,在这里总结一下如何完整的封装一个组件来使用:
- 建立组件的模板,先把架子搭起来,写写样式,考虑好组件的基本逻辑。
- 准备好组件的数据输入。即分析好逻辑,定好
props
里面的数据、类型。 - 准备好组件的数据输出。即根据组件逻辑,做好要暴露出来的方法。
- 封装完毕了,直接在其他页面调用即可。
关于组件的创建使用可以看一下:13. 自定义全局弹出框组件的实现 就明白了如何创建封装一个组件了。
-
引入
Vuex
实现数据共享Vuex
是一个专门为Vue.js
应用程序开发的状态管理模式,它采用集中式存储管理所有组件的公共状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 的优点:
- Vuex 可以保存数组、对象、或者嵌套结构,不用
toString
- 双向绑定,使用
commit
修改一处状态后,所有引用的地方自动更新,不需要重新取值 - 可以自定义数据过滤方法、取值方法、逻辑判断等
- 可以在 Vuex 里封装
Ajax
下·请求,外部只负责调用数据
关于这一部分的优化使用,可以看一下:12. 引入Vuex实现数据管理以及登录流程的实现
- Vuex 可以保存数组、对象、或者嵌套结构,不用
-
Vue 公共样式处理
在项目中我们有一些公共样式是一样的,我们可以对这些样式进行提取,然后在我们需要的地方引入即可,也可以将部分公共样式放到 App.vue 中。
比如:弹出动画的css相同,提取一个公共动画样式
- 在
src/common/style
目录下, 新建common.less
.up-enter-active, .up-leave-active { transition: all .5s; } .up-enter, .up-leave-to /* .fade-leave-active below version 2.1.8 */ { opacity: 1; transform: translateY(100%); }
- 然后在需要用到的文件中引入
<style lang="less" scoped> @import "../common/styles/common.less"; </style>
- 在
-
Vue 路由拆分
当我们项目的路由文件
index.js
内配置特别多以及多人同时开发时将面临如下问题:- 文件冲突
- 文件内容庞大 不利于优化
此时我们可以对路由
index.js
进行拆分,将index.js
拆分为如下结构:index.js 路由创建 routers.js 页面路由配置 module 路由模块 home.js 主页面路由 sign.js 登录页面路由 publish.js 发布页面路由
通过如下步骤的拆分,这样就避免了如上问题,以后再配置新的路由 就很简单了。
模块里的页面配置还是之前的相同配置,只不过将这些内容提取出来变成一个个模块来导入使用。
具体代码如下:
src/router/index.js
import Vue from 'vue'; import VueRouter from 'vue-router'; import routes from './routers'; Vue.use(VueRouter); const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes, }); // 解决重复点击导航时,控制台出现报错 const VueRouterPush = VueRouter.prototype.push; VueRouter.prototype.push = function push(to) { return VueRouterPush.call(this, to).catch(err => err); }; // 设置登录权限,用户未登录时需要前往登录 router.beforeEach((to, from, next) => { const { meta: { requiresAuth } } = to; // 获取当前用户是否登录 console.log(to, from); const isLogin = sessionStorage.getItem('isLogin'); if (requiresAuth && !isLogin) { next({ path: '/sign' }); } else { next(); } }); export default router;
src/router/routers.js
… 为ES6扩展运算符
import home from './module/home'; import sign from './module/sign'; import publish from './module/publish'; import edit from './module/edit'; const routes = [ { path: '/', redirect: '/index/recommend', }, { path: '/index', redirect: '/index/recommend', }, ...home, ...sign, ...publish, ...edit, ]; export default routes;
src/router/module/home.js
import Home from '@/views/Home.vue'; const home = [ { path: '/', name: 'Home', component: Home, children: [ { path: '/index', name: 'index', component: () => import(/* webpackChunkName: "index" */ '@/views/index/index.vue'), children: [ { path: 'follows', name: 'follows', component: () => import(/* webpackChunkName: "follows" */ '@/views/follow/index.vue'), children: [ { path: 'reVideoList', name: 'reVideoList', component: () => import(/* webpackChunkName: "VideoList" */ '@/common/components/videoList/VideoList.vue'), }, ], }, { path: 'recommend', name: 'recommend', component: () => import(/* webpackChunkName: "recommend" */ '@/views/recommend/index.vue'), children: [ { path: 'reVideoList', name: 'reVideoList', component: () => import(/* webpackChunkName: "VideoList" */ '@/common/components/videoList/VideoList.vue'), }, ], }, ], }, { path: '/friends', name: 'friends', component: () => import(/* webpackChunkName: "friends" */ '@/views/friends/index.vue'), }, { path: '/news', name: 'news', component: () => import(/* webpackChunkName: "news" */ '@/views/news/index.vue'), meta: { requiresAuth: true, // 是否需要登录权限 }, }, { path: '/mine', name: 'mine', component: () => import(/* webpackChunkName: "mine" */ '@/views/mine/index.vue'), meta: { requiresAuth: true, // 是否需要登录权限 }, }, ], }, ]; export default home;
src/router/module/sign.js
const sign = [ { path: '/sign', name: 'Sign', component: () => import(/* webpackChunkName: "sign" */ '@/views/Sign.vue'), }, { path: '/codeSign', name: 'codeSign', component: () => import(/* webpackChunkName: "code" */ '@/views/Code.vue'), }, ]; export default sign;
src/router/module/edit.js
const edit = [ { path: '/edit', name: 'edit', component: () => import(/* webpackChunkName: "edit" */ '@/views/mine/editInfo.vue'), }, { path: '/update', name: 'update', component: () => import(/* webpackChunkName: "edit" */ '@/views/mine/updateInfo.vue'), }, ]; export default edit;
src/router/module/publish.js
const publish = [ { path: '/publish', name: 'publish', component: () => import(/* webpackChunkName: "publish" */ '@/views/publish/index.vue'), }, ]; export default publish;
注意:我们使用
ESLint + Standard
代码规范,在进行模块成员导出时,请使用export default
的方式导出,使用import xx from '@/xxx
的方式导入,具体使用如上。
打包与部署
经过前面章节的开发,我们完成了 vue实战项目的全部内容,下面我们将进行项目打包与部署。
我们在使用 Vue 做前后端分离项目时,通常前端是单独部署,用户访问的也是前端项目地址,因此前端开发人员很有必要熟悉一下项目部署的流程与各类问题的解决办法了。
其实 Vue 项目打包部署本身不复杂,不过对于服务器接触不多,但是实际工作过程中一般是不需要我们前端人员进行部署的,所以这里只需要了解一下项目是如何部署的就可以了。
默认情况下,使用 vue-cli
创建的项目,package.json
里的 script
应该已经配置了 build
指令,直接执行 yarn build
或者 npm run build
即可。
yarn build
OR
npm run build
// 以上两个指令最终运行的代码是 vue-cli-service build
我们的项目一般是通过 nginx
进行转发的,nginx
的转发规则是需要配置上下文的,为了解决这个问题,我们需要对 vue.config.js
、env.production
、env.development
以及 router
下的 index
进行修改
-
vue.config.js
module.exports = { // 设置打包文件输出路径 outputDir: process.env.NODE_ENV === 'production' ? 'dist': 'dy' , // 生产环境是否生成SourceMap productionSourceMap: false, // 资源访问路径 publicPath: process.env.VUE_APP_NGINX_CONTENT, }
-
env.production
NODE_ENV="production"; # 是否开启移动端调试 VUE_APP_ERUDA=false BASE_URL='/' VUE_APP_BASE_API="/prod-api" # nginx 上下文 VUE_APP_NGINX_CONTENT = '/'
-
env.development
NODE_ENV="development"; BASE_URL='/' # 是否开启移动端调试 VUE_APP_ERUDA=true VUE_APP_BASE_API="/dev-api"
-
router/index.js
const router = new VueRouter({ mode: 'history', // base: process.env.BASE_URL, base: process.env.VUE_APP_NGINX_CONTENT, routes, });
项目开发完成需要部署时,都需要将接口等配置文件更新成服务器地址,然后打包发布部署就可以了。
测试打包代码
上面我们对 Vue 项目进行打包以及线上地址的配置,打包完成后我们通常需要在本地进行测试一下,然后再放到服务器上,以免将有问题的代码部署到服务器上。
-
将代码打包
上面我们以及打包过了,不再赘述
yarn build
-
根目录下新建
app.js
文件 -
配置
app.js
文件var express = require('express'); var fs = require('fs'); var http = require('http'); var app = express(); app.use(express.static('./dy')); app.use(function (req, res,next) { res.sendFile('./dy/index.html'); //路径根据自己文件配置 }); var httpsServer = http.createServer(app); httpsServer.listen(8888, function () { var host = '127.0.0.1'; var port = httpsServer.address().port; console.log('app listening at http://%s:%s', host, port); });
-
运行
app.js
node app.js // => app listening at http://127.0.0.1:8888
-
在浏览器上访问该地址即可。
至此,大功告成!
上一章节: 19. 发布页面的实现(摄像头调用,视频录制等功能)
下一章节: 21. 项目总结
项目整体介绍:Vue.js 项目实战之实现视频播放类WebApp的项目开发(仿抖音app)
项目仓库地址,欢迎 Star。
有任何问题欢迎评论区留言讨论。