Vue实现20+页面的复杂单页面应用(仿实验楼)

前言

初学Vue,搜Vue项目时出现的几乎都是TODO应用,音乐播放器之类复杂度并不如想象中高的应用,固然慢慢摸索实现出来也会知道Vue的一些功能,v-on,v-bind之类的绑定,v-for,v-if 等逻辑控制。但写完总感受意犹未尽... 因而想实现一个稍微复杂些的应用。css

项目主要实现的是前端页面部分,数据来源于实验楼原站,原站API不支持跨域调用,须要使用一个转发html

效果展现

路径
课程
课程

线上演示(Github Page)前端

技术栈

vue2 + vuex + vue-router + axios + flexvue

知识点总结

vue-router

懒加载

路由懒加载由官方文档中说明的做用是打包应用时的按需加载:最终的目的老是要打包发布,因此懒加载必定要知道。ios

const __import__ = file => () => import(`@/pages/${file}.vue`)
...
{
    name: 'home',
    component: __import__('home') 
}
复制代码

路由切换过渡动画

单页面应用能够很方便的制做切换不一样页面时使用的动画效果,像是手机APP中的左滑右滑之类的。这里实现的过渡动画效果是透明度由0到1的缓慢渐变浮现效果。使用Vue的过渡动画组件便可 git

过渡

<template>
  <div id="app">
    <transition name="tab_router_view">
      <router-view></router-view>
    </transition>
  </div>
</template>
<style> .tab_router_view-enter-active, .tab_router_view-leave-active { transition: opacity .8s; } .tab_router_view-enter, .tab_router_view-leave-to { opacity: 0; } .tab_router_view-enter-to, .tab_router_view-leave { opacity: 1; } </style>
复制代码

这样每次切换路由时都会触发一个透明度从0到1的0.8秒渐变效果: github

渐变

路由导航守卫

路由导航守卫能够在每次路由变化时让咱们作一些功能性的调整,如切换的这个页面若是须要登陆那么咱们能够这样:vue-router

...
{
    path: '/profile',
    name: 'profile',
    component: Profile,
    meta: {
        login: true
    }
}
router.beforeEach((to, from, next)=>{
    if (to.meta.login) {
        if (!store.state.loginState.isLogin) {
            next({name: 'login'})
        } else {
            next()
        }
    }
})
复制代码

上面的守卫实现了若是当前页面要求登陆但没有登陆的话会跳转到登陆页面,这样就不须要每一个页面都设置一遍检查了, 另外前置导航守卫必定要记得调用next,不然不会有组件加载出来。vuex

每次切换路由页面后咱们极可能还须要一个后置导航守卫来替咱们将页面滚到最上部npm

router.afterEach((to, from) => {
    window.scrollTo(0, 0)
})
复制代码

区别于前置守卫,后置守卫没有next须要调用。

vuex

vuex被用来进行状态管理,这是一个全局的数据仓库一类的东西,数据的下载,转换,保存都放在里面进行。Vue的组件里固然也能够进行数据的下载保存,也能够进行不一样组件件的传递,但随着业务增多每每会变得至关麻烦。

不用vuex状态管理的话通常会顺着思路这么写:

数据由父组件下载并保存下来传递到子组件:

<SubComponent :data="dataOne">
</SubComponent>
...
data: function () {
    return {
        dataOne: {}
    }
},
created: async function () {
    let res = await get('http://www.ceshi.com')
    this.dataOne = res.data
}
复制代码

子组件内有一个触发填好后发起页面修改,但子组件是不能直接修改父组件传递过来的数据的,因此又须要发送一个信号让父组件接受后由父组件修改:

子组件

props: {
    data: {
        type: Object,
        require: true
    }
},
methods: {
    change: fucntion (data) {
        this.$emit('change', data)
    }
}
复制代码

父组件

<SubComponent :data="dataOne"
              @change="change"
>
</SubComponent>
...
methods: {
    change: async function (data) {
        await get(...)
    }
}
复制代码

多写了一个change方法不说,还须要不忘记注册子组件的事件,想一想这只是两个组件间的通讯,随着组件的增多,原本只须要一个方法的事情会须要两个三个,事件的注册也愈来愈多,取决于嵌套了多少子组件,稍微不注意忘了注册哪一个事件就要debug很长时间。

若是用了vuex就会简单不少,由于它是一个全局的状态管理。

父组件只须要负责把触发数据下载。

<SubComponent></SubComponent>
...
created: async function () {
    await this.$store.dispatch('dataStore/getData')
}
复制代码

子组件内的数据就会跟随更改,修改数据也不用再通知父组件

computed: {
    dataOne: function () {
        return this.$store.state.dataStore.dataOne
    }
},
methods: {
    change: async function (data) {
        await this.$store.dispatch('dataStore/getData', data)
    }
}
复制代码

这样的全局状态管理不会由于嵌套的子组件而增长复杂度,并且具备良好的可读性,如何操做数据在store里进行修改,组件里只须要触发便可。

API跨域配置

实验楼原站也是使用Vue编写,先后端分离,使用API通信,咱们能够把API抓取下来使用,固然我已经抓好了,实验楼API后端,实验楼的API与展现在同一个域名下,因此不存在跨域问题,但咱们开发的话就不是在同一个域名下,要使用的话绕不开的一环就是跨域了。因为服务器端不支持跨域,要使用只能作一个转发,先来了解一下跨域吧。

同源策略

同源策略限制了从同一个源加载的文档或脚本如何与来自另外一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。也就是说 在http://www.baidu.com的Js,若是没有跨域配置是没法与http://juejin.im进行通信的。

服务器端跨域配置

无论后端使用何种语言,要解决跨域就是要让服务器的回复中添加如下头:

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods:POST
Access-Control-Allow-Headers:x-requested-with,content-type
复制代码

Access-Control-Allow-Origin 表示能够请求的源,*表示任意一个均可以。

Access-COntrol-Allow-Methods 表示请求时的方法,POST表示只有POST请求才能够进行跨域请求,GEt,PUT,DELETE之类的若是没有标明通通不能够。

Access-Control-Allow-Headers表示跨域容许的首部。

Vue中的配置

本地开发的话能够在Vue的配置文件中进行配置config/index.js,下面是配置的开发环境的跨域请求:

dev: {
    proxyTable: {
          '/api': {  
            target: 'http://localhost:8000/api',// 设置你调用的接口域名
            changeOrigin: true,  
            pathRewrite: {  
              '^/api/': '' // 这里替换的是 target 中的内容,使用的时候 '/api/demo' 就至关于'http://localhost:8000/api/demo'。
            }  
          }
    }
}
复制代码

生产环境下的跨域:

生产环境下若是跨域不须要携带cookies认证那服务器配置了上面说的几个响应头便可,不然的话还须要

Access-Control-Allow-Credentials:true
复制代码

以及

Access-Control-Allow-Origin
复制代码

不能够为**与credentials是冲突的。

最后使用 axios 请求时须要配置withCredentials = true

CSS布局

项目中使用了flex布局,flex布局使用起来比较流畅,写起来也很简单,任意元素加上

.box {
    display: flex
}
复制代码

这样这个元素的内容就会按照默认的flex进行布局

布局
默认水平走向,不会换行,从容器的最左端开始排列。 容器里元素的如何排列咱们能够经过这些属性来设置:

flex-direction  排列方向 row | column
flex-wrap wrap | nowrap
flex-flow 上面两个的简写 row nowrap
justify-content 指定元素主轴(main axis)对其方式 flex-start | flex-end | center | space-between | space-around
align-items 指定元素交叉轴(corss axis)对其方式 flex-start | flex-end | center | baseline | stretch
复制代码

了解上面这一点就能够把常规的布局方式熟悉一下,只用上面这些就能够搭建出首页。

这里是关于flex更详细的资料

最后

完整的项目请看GitHub

克隆后直接启动便可:

git clone git@github.com:HuberTRoy/vue-shiyanlou.git

cd vue-shiyanlou

npm install

npm run dev
复制代码

若是对您有帮助,但愿能够获得一枚您的Star~。(〃'▽'〃) 有任何能够改进的地方但愿您能够花费一些时间开启一个Issue或者直接PR~。φ(>ω<*)

相关文章
相关标签/搜索