项目时间:2019.8-2019.8
项目名称:医院管理系统
项目工具:windows
项目介绍:
该系统是为了管理医院信息(如病人、药房、医生信息),且根据不同人的权限让他们可以使用不同的功能。
该系统利用JavaScript语言在Visual Studio Code平台上进行开发,其中前端部分使用了Vue框架,其中引入了Element UI组件库,后端部分使用了Koa2框架,使用vue-resource进行前后端交互,使用mysql数据库进行联合开发。
我的职责:
前端导航,病人,医生,主页面的代码编写与调试

1、怎么检测用户是否登录?怎么拦截没有登录的人?

登录检测的做法:

beforeEach+axios拦截

  • beforeEach是在每一个需要登录权限的路由进入之前检测是否具有登录权限。(在路由跳转前拦截)

  • 登陆成功之后状态存在vuex中,存在sessionStorage里,防止刷新就没了。
    图片说明

  • 然后beforeEach里检查本地存储中的登录信息,如果登录信息正确,则进行跳转,否则就是登录页。

  • axios请求拦截(在请求接口调用时触发)

1、beforeEach前置路由守卫。

  • 首先在定义路由的时候就需要多添加一个自定义字段 requireAuth ,用于判断该路由的访问是否需要登录。如果用户已经登录,则顺利进入路由, 否则就进入登录页面。
  • 在main.js里有全局的前置路由守卫,在每次路由跳转的时候检测是否登陆,用sessionStorage里的token和检查下一个路由是否是login
    if (to.meta.requireAuth) { // 判断该路由是否需要登录权限
    图片说明
    这种方式只是简单的前端路由控制,并不能真正阻止用户访问需要登录权限的路由。还有一种情况便是:当前token失效了,但是token依然保存在本地。这时候你去访问需要登录权限的路由时,实际上应该让用户重新登录。 这时候就需要结合 http 拦截器 + 后端接口返回的http 状态码来判断。

2、在axios请求拦截:

//我是个什么辣鸡,当年做这个东西为什么会vue-resouce和axios混用??简直惊天地泣鬼神axios的请求拦截器里检测token,有token的话就加上文件头
响应拦截器中,当没有登录,未验证,则会重新回到login,把原来的路由当作参数,登录成功之后跳转
图片说明
图片说明
##2、什么是路由懒加载:
可以理解为promise函数懒加载就是延迟加载或者按需加载,需要的时候进行加载
前端路由懒加载是将一次加载分为按需加载,路由切换时加载资源只是加载要使用的静态文件,和后端路由每次进行页面请求是两件不同的事情,且路由切换后仍然复用了公共资源;
方法:

  • ①使用vue异步组件

  • ②es中的import
    没有使用懒加载:

                  import Vue from 'vue'
                  import Router from 'vue-router'
                  import HelloWorld from '@/components/HelloWorld'
    
                  Vue.use(Router)
    
                  export default new Router({
                    routes: [
                      {
                        path: '/',
                        name: 'HelloWorld',
                        component:HelloWorld
                      }
                    ]
                  })
  • ①vue异步组件component:resolve=>(require(['需要加载的路由的地址'],resolve);//不用使用import

    import Vue from 'vue'
    import Router from 'vue-router'
      /* 此处省去之前导入的HelloWorld模块 */
    Vue.use(Router)
    export default new Router({
    routes: [
      {
        path: '/',
        name: 'HelloWorld',
        component: resolve=>(require(["@/components/HelloWorld"],resolve))
      }
    ]
    })
  • ②es的import方法:最常用
    const HelloWorld=()=>import('模块地址')

    import Vue from 'vue'
    import Router from 'vue-router'
    Vue.use(Router)
    const HelloWorld = ()=>import("@/components/HelloWorld")
    export default new Router({
    routes: [
      {
        path: '/',
        name: 'HelloWorld',
        component:HelloWorld
      }
    ]
    })

    组件懒加载:'one':resolve=>({'./one',resolve}

3、路由模式:使用hash模式

Vue的路由实现:hash模式 和 history模式

hash模式:

在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com, 因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

history模式:

history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

4、登录页面:

  • 使用elementui,通过vue-resourse的post方法提交表单,没有做一个记录的功能。
    如果使用的是axios
    axios.post('/user', {
      firstName: 'Fred',
      lastName: 'Flintstone'
    })
    .then(function (response) {
      console.log(response);
    })
    .catch(function (error) {
      console.log(error);
    });
    图片说明
  • 当关闭这个页面的时候就会失去token,
  • 怎么实现存储多个不同类型的人?没有做这个功能,所以只有登录功能没有注册功能

5、vuex的使用

Vuex 应用的核心就是 store(仓库)

vux和单纯的全局对象有两点不同:

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

  • 不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

vuex四大杀手

  • state 说明了用户登录的状态,保存了要共享的信息,现在要共享的信息就是用户的信息和用户的类型

  • getters 有时候我们需要从store中的state中派生出一些状态。store中的计算属性,返回值会根据它的依赖被缓存起来,只有当依赖改变时才会重新计算,即用户信息改变时重新计算

  • mutations 用于改变state的状态

  • actions

  • state:
    图片说明

  • getters,接受state作为第一个参数,也可以接受其他的getter作为第二个参数
    当getter在通过方法访问时,每次都会去进行调用,而不会缓存结果
    图片说明

  • mutations
    触发方式是:store.commit(...)
    图片说明

  • actions
    store.dispatch()
    图片说明

  • 记录状态
    图片说明

6、导航栏的做法:elementui的导航栏组件

slot的使用

  • slot是一块html模板,这块模板显示不显示、以及怎样显示由父组件来决定
  • 它是一个空壳子,因为它显示与隐藏以及最后用什么样的html模板显示由父组件控制。但是插槽显示的位置确实由子组件自身决定,slot写在组件template的哪块,父组件传过来的模板就显示在哪块。
  1. slot插槽:将父组件的内容和子组件的模板整合的方法:内容分发。在组件标签内部写入的内容默认的会被替换掉,如果想在组件的模板中使用这些内容,就在响应的位置写上slot
  2. 匿名槽口:不用设置name属性,但一个组件只能有一个该类插槽。但具名插槽就可以有很多个。父组件中使用子组件时,在子组件标签内部写的内容给,在子组件的模板中可通过slot来使用。在子组件中写入slot,slot所在的位置就是父组件要显示的内容
  3. 具名插槽:加了name属性,具名插槽可以出现n次。所以在子组件中哪里出现了这个名字就插到哪里。
  4. 作用域插槽 | 带数据的插槽:要在slot上面绑定数据 :data=“data”,作用域插槽绑定了一套数据,父组件可以拿来用,样式父组件说了算,但是内容可以显示子组件插槽绑定的。

!!!!除了登录以外,其实我们做的是一个单页面窗口,是导航栏为主体的,通过vue-router来实现各种组件,设导航为router-link,上面有一格v-header,把右边设为router-view。

!!!怎么实现导航栏的放大和缩小:单纯的导航栏放大缩小是elementui做的,他设置了一个smallNav的类,当要拉开的时候设置为false,要缩小的时候设置为true,然后就可以设置点击某个方法给他改变设置。但是整个背景的设置是,首先设置他拉开之后的效果,然后在smallNav变化的时候,即这个类出现的时候,给smallNav设置一个样式,这时候,smallNav的样式就能够覆盖前面menu的样式,从而实现样式的转变

7、添加医生信息:

①用elementui的表单验证组件,给整个表单设置rules,并且设置form,里面有所有需要的数据。当离开输入框的时候触发change和blur,当为blur时触发:还有change和blur很相似,但是没有任何输入和输入后值没有发生变化时change不会触发。

8、查看医生信息:

①表格部分用了table组件,表格里使用了slot-scope,用于传递信息,比如获取某一行的信息,获取某个的信息用来处理
②弹窗部分用了dialog组件,
弹窗的内容和前面的表格的内容是怎么做到同步的呢
③页面翻动是怎么做的:使用了pagination分页组件
1、表格头:使得获取的数据是每一页而不是全部

:data="userList.slice((currentPage-1)*pagesize,currentPage*pagesize)" 

2、翻页组件:

<el-pagination
                            @size-change="handleSizeChange"
                            @current-change="handleCurrentChange"
                            :current-page="currentPage"
                            :page-sizes="[5, 10, 20, 40]" //这是下拉框可以选择的,每选择一行,要展示多少内容
                            :page-size="pagesize"         //显示当前行的条数
                            layout="total, sizes, prev, pager, next, jumper"
                            :total="userList.length">    //这是显示总共有多少数据,
                    </el-pagination>

3、获取数据

created() {
        this.handleUserList()
    },
    methods: {
        // 初始页currentPage、初始每页数据数pagesize和数据data
        handleSizeChange: function (size) {
                this.pagesize = size;
                console.log(this.pagesize)  //每页下拉显示数据
        },
        handleCurrentChange: function(currentPage){
                this.currentPage = currentPage;
                console.log(this.currentPage)  //点击第几页
        },
        handleUserList() {
            this.$http.get('http://localhost:3000/userList').then(res => {  //这是从本地请求的数据接口,
                this.userList = res.body
            })
        }
    }

搜索部分:带参数

 let intendedSearch = this;
      intendedSearch.$http
        .get("/api/doctor/query", {
          params: { doctorName: intendedSearch.searchName }
        })

技术难点:
1、如何将导航栏固定在左侧
2、vue-router
3、webpack模块热更新:目的是加快用户的开发速度,但是只能在开发环境中使用,模块热替换,允许在运行时替换、添加、删除各种模块,而无需进行完全刷新重新加载整个页面
4、axios
1、基于promise的http库,可以用在浏览器和nodejs里
1、request和response拦截器
在请求或响应被then和catch处理前拦截他们
请求拦截器:会在发送请求之前运行,给他们统一加东西
请求拦截器:axios.interceptors.request.use(function (config){return config;},function(error){return Promise.reject(error);})

响应拦截,做统一处理
响应拦截器:axios.interceptors.response.use(...)
router的属性:router.app/router.mode/router.currentRoute当前路由的路由信息对象,包含了当前匹配的路由信息
route的方法:addRoute(routes)/router.beforeEach(to,from,next)
route是路由信息对象,包含和当前路由的各种信息