# 医保网厅架构介绍

# api

在我们开发的时候按照模块或者页面来区分开调用的接口,并把他们放在一起方便管理

例如: 在@api/modules/下创建一个setting-api.js

import axios from "../common-axios.js" // 引用axios

const pathLogin = `/pgs/gw/usc-nation/api`    // 地址变量看具体项目而定
const path = `/hsa-pss-pw/web/elc`            // 地址变量看具体项目而定

export const getQRCode = (params) => axios.post(`${path}/getQRCode`, {
  data: params
})

export const getQRCodeStatus = (params) => axios.post(`${path}/getQRCodeStatus`, {
  data: params
})

export const refresh = (params) => axios.post(`${pathLogin}/login/refresh`, {
  data: params
})

推荐以下这种形式写

export const getQRCode = function(params) {
  return axios({
    url: `${path}/getQRCode`,
    method: "post",
    data: params // 如果请求方式不是post需要将data改为params
  })
}

值得注意的一点是:如果请求方式不是post需要将data改为params

完成之后我们在index.js中引入,再通过index.js统一导出

import * as setting from "./modules/setting-api"

export {
  setting
}

最后我们在页面上调用这里

<script>
import { setting } from "@api/index"   // 引入我们需要的接口模块
export default {
  created() {
    // 通过链式调用接口
    // params指接口参数 如: {name: "guoruliang", password: "123456"}
    setting.getQRCode(params).then(res => {})
    setting.getQRCodeStatus(params).then(res => {})
    setting.refresh(params).then(res => {})
  },
  data() {
    return {}
  },
  components: {},
  methods: {}
}
</script>

# jsconfig.json

文件路径引导

我们使用vscode的时候,如果我们使用了别名就无法联想路径了,这很可能导致我们手敲从而打错路径,这里我们需要安装一个vscode插件

vscode插件搜索 Path Autocomplete

之后再项目的根目录创建jsconfig.json文件,并添加代码如下

{
    "compilerOptions": {  
        "baseUrl": ".",
        "paths": { // 这里的配置根据vue.config.js中的别名配置进行配置
            "@/*": ["src/*"],
            "@utils/*": ["src/utils/*"],
            "@api/*": ["src/api/*"],
            "@components/*": ["src/components/*"],
            "@pic/*":["src/assets/img/*"],
            "@pages/*": ["src/pages/*"]
        },
        "target": "ES6",
        "allowSyntheticDefaultImports": true
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules"]
}

# Vue.config.js

# preload和 Prefetch

懒加载失效的原因:preload 和 Prefetch 链接将会消耗带宽。如果你的应用很大且有很多 async chunk,*而用户主要使用的是对带宽较敏感的移动端,*那么你可能需要关掉 prefetch 链接并手动选择要提前获取的代码区块,但是官网文档是错的要自己打印出来看看 console.log(config) 因为他改名字了

chainWebpack: config => {
   config.plugins.delete("prefetch-index")
   config.plugins.delete("preload-index")
}

# 打包分割splitChunks

配合懒加载使用,有兴趣的可以自己结合webpack文档看看

config.optimizationsplitChunks({
        chunks: "async",   // 参数 all:全部 async:异步 initial:同步  默认:async
        minSize: 30000,    // 最小尺寸 默认30000 单位字节 ,如果我们导入的文件小于30000就直接合并如果大于就进行文件的分割
        maxSize: 50000,    // 最大尺寸 单位字节,如果我们导入的包经过打包后还是大于50000则继续分割,直到小于50000为止(但是如果这个代码无法分割就不分割了)
        minChunks: 1, // 引用次数超出1就分割
        maxAsyncRequests: 5, // 最大的模块引用数 引入的前5个会进行分割打包,超过5不打包
        maxInitialRequests: 3, // 最大的入口文件引用数,引入的前3个会进行分割打包,超过3个不会打包
        automaticNameDelimiter: '~', // 名称连接符
        name: true, // 默认就是true 来标明一下cacheGroups是否生效
        cacheGroups: { // 这里的匹配规则是,是否满足vendors规则,满足则按照vendors的规则分割,
                       // 不满足就去default,还不满足就不打包,当两个规则都符合就比较priority
                       // 哪个大就按哪个来
            vendors: { 打包组 如果是从node_modules导入就统一归类到vendors组
                test: /[\\/]node_modules[\\/]/, // 匹配规则
                priority: -10
            },
            default: { 默认打包组
            	  minChunks: 1, // 引用次数超出1就分割
                priority: -20, 
                reuseExistingChunk: true // 如果我们打包的文件已经被打包过了,就忽略掉,不打包第二次了
            }
        }
    })

# Gzip

开启Gzip极大的减少包的大小,(在一个1M带宽的服务器下)原本首屏需要17s多的首屏加载,经过Gzip的优化处理只需要5s,可见这个速度

项目配置 vue.config.js

configureWebpack: (config) => {
    const productionGzipExtensions = ["js", "css"]
    if (isProd) {
      // 生产环境
      config.plugins.push(
        new CompressionWebpackPlugin({
          filename: "[path].gz[query]",
          algorithm: "gzip",
          test: new RegExp(`\\.(${productionGzipExtensions.join("|")})$`),
          threshold: 20240,
          minRatio: 0.8
        })
      );
    } else {
      // 开发环境
    }

nginx服务器配置

#开启和关闭gzip模式(on|off),开启gzip,需设置为on
gzip on;

# vuex

vue状态管理

目录结构如下:

├── store	(vuex)						# vue状态管理
    ├── modules             # 模块化vuex
    │   └── common.js                                
    └── index.js						# vuex入口           

# common.js

const common = {
  // 存储变量的
  state: { 
    test: "我是vuex测试"
  },
  // 获取变量、类似于计算属性
  getters: {
    test: state => state.test
  },
  // 对变量进行操作的  支持异步操作
  actions: {
    setTest: ({ commit }, val) => {
      setTimeout(() => {
        commit("SET_TEST", val)
      }, 5000)
    }
  },
  // 对变量进行操作的  不支持异步操作
  mutations: {
    SET_TEST(state, val) {
      state.test = val
    }
  }
}
export default common

# index.js

import Vue from "vue"
import Vuex from "vuex"
import common from "./modules/common"

Vue.use(Vuex)
const store = new Vuex.Store({
  modules: {
    common
  }
})

export default store

如何使用:

# child.vue

<template>
 <div class="container">
   子路由1
   {{test}}/{{xx}}
 </div>
</template>

<script>
import { mapGetters } from "vuex"
export default {
  components: {},
  name: "child1",
  watch: {},
  computed: {
    ...mapGetters([  // 方式1
      "test"
    ])  
  },
  props: {},
  filters: {},
  data() {
    return {
      xx: this.$store.getters.test // 方式2
    }
  },
  created() {},
  mounted() {},
  methods: {

  },
  destroyed() {}
}
</script>

<style scoped>

</style>

# Vuex-demo.js

<template>
 <div class="container">
   vuex

   <button @click="changeVuex">修改vuex的值</button>
   <button @click="changeVuex2">修改vuex的值2</button>
 </div>
</template>

<script>
import { mapMutations, mapActions } from "vuex" // 引入
export default {
  components: {},
  name: "vuex",
  watch: {},
  props: {},
  filters: {},
  data() {
    return {

    }
  },
  created() {},
  mounted() {},
  methods: {
    ...mapMutations(["SET_TEST"]), // 方式1 mutations
    ...mapActions(["setTest"]), // 方式1 actions
    changeVuex() {
      // 两种方式效果相同
      this.SET_TEST("是我mutations改的") 
      // this.$store.commit("SET_TEST", "是我mutations改的") // 方式2
    },
    changeVuex2() {
      // 两种方式效果相同
      this.setTest("是我actions改的")
      // this.$store.dispatch("setTest", "是我actions改的") // 方式2
    }
  },
  destroyed() {}
}
</script>

<style scoped>

</style>


# 本地存储(websStorage和Cookie)

# localStorage和sessionStorage

localStorage长期存在,需要手动清空才会消失

sessionStorage浏览器关闭后清空

两者本质上没什么区别用法也相同

const ls = window.localStorage // 或 const ls = window.sessionStorage
// sessionStorage
// localUtil
export default {
  getItem (key) {
    try {
      return JSON.parse(ls.getItem(key))
    } catch (err) {
      return err
    }
  },
  setItem (key, val) {
    try {
      ls.setItem(key, JSON.stringify(val))
    } catch (err) {
      return err
    }
  },
  clear () {
    ls.clear()
  },
  keys () {
    return ls.keys()
  },
  removeItem (key) {
    ls.removeItem(key)
  }
}

使用

<template>
  <div class="container">
    <button @click="setSessionStorage">设置sessionStorage</button> 
    <button @click="getSessionStorage">获取sessionStorage</button>
    <button @click="removeSessionStorage">移除sessionStorage</button> 

		<button @click="setLocalStorage">设置localStorage</button> 
    <button @click="getLocalStorage">获取localStorage</button>
    <button @click="removeLocalStorage">移除localStorage</button> 

    <button @click="setCookie">设置Cookie</button> 
    <button @click="getCookie">获取Cookie</button> 
    <button @click="removeCookie">移除Cookie</button>
  </div>
</template>

<script>
import sessionStorage from "@utils/sessionStorage"
// import localStorage from "@utils/localUtil"
import cookie from "@utils/cookie"

export default {
  components: {},
  name: "storage",
  watch: {},
  props: {},
  filters: {},
  data() {
    return {
    }
  },
  created() {},
  mounted() {},
  methods: {
    // 设置localStorage
    setLocalStorage() {
      localStorage.setItem("user", "我")
    },
    // 获取localStorage
    getLocalStorage() {
      console.log(localStorage.getItem("user"))
    },
    // 移除localStorage
    removeLocalStorage() {
      localStorage.removeItem("user")
    },
    // 设置sessionStorage
    setSessionStorage() {
      sessionStorage.setItem("user", "我")
    },
    // 获取sessionStorage
    getSessionStorage() {
      console.log(sessionStorage.getItem("user"))
    },
    // 移除sessionStorage
    removeSessionStorage() {
      sessionStorage.removeItem("user")
    },
    // 设置Cookie
    setCookie() {
      cookie.setCookie("user", "我", 24*60*60*1000) // 一天后过期
    },
    // 获取Cookie
    getCookie() {
      console.log(cookie.getCookie("user"))
    },
    // 移除Cookie
    removeCookie() {
      cookie.removeCookie("user")
    }
  },
  destroyed() {}
}
</script>

<style scoped>
</style>

与webStorage的区别是Cookie可以自己设置过期时间

function setCookie(key, value, iDay) {
  var oDate = new Date();
  oDate.setDate(oDate.getDate() + iDay);
  value = JSON.stringify(value)
  document.cookie = key + '=' + value + ';expires=' + oDate + ';path=/';

}

function removeCookie(key) {
  setCookie(key, '', -1); //这里只需要把Cookie保质期退回一天便可以删除
}

function getCookie(key) {
  var cookieArr = document.cookie.split('; ');
  for (var i = 0; i < cookieArr.length; i++) {
    var arr = cookieArr[i].split('=');
    if (arr[0] === key) {
      try {
        return JSON.parse(arr[1])
      } catch (err) {
        return err
      }
    }
  }
  return false;
}

function clearCookie() {
  var keys = document.cookie.match(/[^ =;]+(?=\=)/g);
  if (keys) {
    for (var i = keys.length; i--;)
      document.cookie = keys[i] + '=0;expires=' + new Date(0).toUTCString()
  }
}

export default {
  setCookie,
  removeCookie,
  getCookie,
  clearCookie
}


# vue-router

# 路由设置

export default [
  {
    path: "/",
    redirect: "/home" // redirecet 重定向
  },
  {
    path: "/home",
    name: "home",
    meta: {
      keepAlive: false,/*不需要被缓存 */
      title: "首页",
      icon: 'example'//展示的图标
    },
    redirect: '/index',
    component: () => import(/* webpackChunkName: "home" */ "@/views/home.vue"),
    children: [ // 路由嵌套 子路由
      {
        path: "child1",
        name: "child1",
        meta: {
            title: "子页面1",
        },
        component: () => import(/* webpackChunkName: "home" */ "@/views/child1.vue"),
      },
      {
        path: "child2",
        name: "child2",
        component: () => import(/* webpackChunkName: "home" */ "@/views/child2.vue"),
        meta: {
            title: "子页面2"
        },
      }
    ]
  }
]
  
  • redirecet 路由重定向

  • children 路由嵌套

  • /* webpackChunkName: "home" */ 魔法注释,将webpackChunkName同名的打包成一个包,在页面没有调用

    打包内容的路由时浏览器不会进行加载

效果展示:children嵌套输出类似如下开关路由导航: navbar

# Vue-router的跳转方式

//方式一:在页面中跳转  在设置tag属性前  router-link本质上就是个a标签   tag设置成button则搭载在button标签上
//不带参数:
<router-link :to="{path:'/home'}" tag="button">vuex</router-link>
//带参数
<router-link :to="{path:'/home',query:{id:1,yourname:'myname'}}" tag="button">vuex</router-link>

//方式二: 通过浏览器地址传值,刷新浏览器  参数不会消失
this.$router.push({ path: "/storage", query: { name: "我是从home来的query" }})

路由跳转使用方式

<template>
  <div class="container">
    <ul>
      <li>
        <router-link to="/axios">axios</router-link>
      </li>
      <li @click="goStorage">
        storage 
      </li>
      <li>
        <router-link  :to="{path:'/home/child1'}">child1</router-link>
      </li>
      <li>
        <router-link :to="{path:'/home/child2',query:{id:1,yourname:'myname'}}">child2</router-link>
      </li>
    </ul>
    <div class="children">
      <router-view></router-view>
    </div>
  </div>
</template>
<script>
import { setting } from "@api/index"
export default {
  created() {
    setting.getQRCode().then(res => {})
    setting.getQRCodeStatus().then(res => {})
    setting.refresh().then(res => {})
  },
  data() {
    return {}
  },
  components: {},
  methods: {
    goStorage() {
      // 函数跳转方式
      this.$router.push({
        path: "/storage",
        query: { name: "我是从home来的query" }
      })
    }
  }
}
</script>
<style lang="scss">
.container {
  width: 100%;

  ul {
    overflow: hidden;
  }

  li {
    float: left;
    margin: 10px;
  }

  .children {
    width: 500px;
    height: 500px;
    border: 1px solid #000;
    background-color: $theme-blue;
  }
}
</style>


刷新页面js调用:this.$router.go(0)

# 获取URL中的路由传参

<template>
  <div class="container">
    {{name}}
  </div>
</template>

<script>

export default {
  components: {},
  name: "storage",
  watch: {},
  props: {},
  filters: {},
  data() {
    return {
      name: this.$route.query.name//url假设是:xxxx?name=zhangsan 
    }
  },
  created() {},
  mounted() {},
  methods: {
    
  },
  destroyed() {}
}
</script>

<style scoped>
</style>

更新时间: 4/27/2020, 11:52:51 AM