前端的大体流程:

        首先是Login登录组件,当输入用户名和密码之后,发送post请求到后端,然后根据返回的数据的是否正常,如果正常,将返回的token以及用户名保存到sessionStorage中,并使用导航守卫进行跳转到主页面。主页面中有默认页面,目前没有做,本打算默认页面是显示所有服务的服务状态以及可以重启按钮等操作的,除了默认按钮之外就是就是应用名(*宝和*神)。然后当点击这两个应用名之后,会显示相对应的服务名,服务名下面是一个表格,这个表格是公共组件的,里面的数据是从Vuex这个公共组件里面获取的,也就是当你点击服务名的时候会将相应的服务名添加到vuex中,这样做的好处是当你点击*神的时候,下面的公共组件也会显示*宝的服务名,当点击*宝的时候也会显示*神的服务名。


疑问:对于前端的页面认证,我使用的是给路由中添加元数据,然后再主入口组件中使用全局守卫进行判断这个元数据,如果满足判断是否已经登录            (去seessionStorage中取值),如果没有登录,使用导航守卫跳转到登录页面。

问题:前端已经做了登录页面验证,后端是否还需要使用DRF中的登录认证组件进行登录页面验证?

如下,定义在入口组件中的全局守卫,相当于一个看门狗,每个请求都会经过这个全局守卫,对元数据是auth:true进行验证。


下来根据主页面来说说主体思路:


先看主入口文件部分内容,导入了很多东西,可以进行全局引用:

import Vue from 'vue'import App from './App'import router from './router'                        #这是路由组件// elementUI 导入import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';// 调用插件Vue.use(ElementUI);//引入全局的组件import Public from './components/Public/Public'        #这是上图中所说的公共组件Vue.component(Public.name,Public);//引入Vuex,进行状态管理                                #这是Vuex,进行状态管理import store from './store'//导入axios                                            #这是axios,以后再其他地方使用this.$http. 的方式引用import * as api from './restful/api'console.log(api)Vue.prototype.$http=api;//导入全局样式import '../static/global/global.css'

下来是路由组件:路由组件中children,字体意思是这个组件有孩子组件,这个children是前端同事帮我加的。和自己之前写的有点差别,不过觉得这个更规范。

import Vue from 'vue'import Router from 'vue-router'Vue.use(Router)import HelloWorld from '@/components/AppName/HelloWorld'import CaiBao from '@/components/CaiBao/CaiBao'import HeShen from '@/components/HeShen/HeShen'import Login from '@/components/Login/Login'import ServiceStatus  from '@/components/ServiceStatus/ServiceStatus'export default new Router({  linkActiveClass: "is-active",  mode: 'history',  routes:[    {      path:'/',                                             #首先是去找Login组件      name:'login',      component:Login    },    {      path:'/heyan/detailpage',                    #登录成功后,登录组件中会使用导航守卫跳转到这个      name:'HelloWorld',      component:HelloWorld,        children:[          {            path: '/',                             #这个是我在开始时说的那个默认显示页面,想用python-ansible-api显示组件相关信息,还没做                                              name: 'ServiceStatus',            component:ServiceStatus,          },            {              path:'/caibao/:userId',               #当在HelloWorld组件中点击router-link时跳转到这里              name:'caibao',              component:CaiBao,              meta:{                  //如果是true,表示访问该组件时需要登录        #前面说的元数据                  auth:true              }            },            {              path:'/heshen/:userId',            #和上面的一样              name:'heshen',              component:HeShen,              meta:{                  //如果是true,表示访问该组件时需要登录                  auth:true                }            },        ]    },  ]})


App组件中只有一行router-view,和Login组件对应,提供出口。


Login组件:  loginHandler方法是点击登录按钮触发的,this.$http.userLogin(params)这个是发送axios请求,并携带参数,这种发送axios请求的方式之前说到的。然后根据返回的值判断是否要健token和用户名存放到sessionStroage,还有就是跳转到HelloWorld组件中。

methods:{  loginHandler(){      let params = {          username:this.username,          pwd:md5(this.password),      };      console.log(params);      this.$http.userLogin(params)      .then(res=>{          console.log(res);          if (!res.data =="") {              sessionStorage.setItem('access_token',res.data);              sessionStorage.setItem('username',res.username);              this.$router.push('/heyan/detailpage');         }      })      .catch(err=>{          console.log(err);      })  },}

HelloWorld组件:根据钩子函数,当这个组件创建的时候会发送一个get请求从而从数据库中获取到相应的应用名,然后根据for循环显示到页面中,最后使用router-link进行跳转到路由中的children部分。需要传递路由参数params。

<script>export default {  name: 'LuffyHeader',  data(){    return{      AppnameList:[],        }  },  created() {    this.getAppnameList();    console.log(123)  },  methods:{    getAppnameList(){      this.$http.appnameList()        .then(res=>{            // console.log(res);            this.AppnameList = res        })        .catch(err=>{          console.log(err);        });    },    }};</script>

helloworld组件中有两个子组件里面的代码是大体相同的,只说一个CaiBao这个组件。

CaiBao组件:当进入这个组件之后首先使用钩子函数created发送一个get请求,主要是获取到根据应用的id获取到相应的服务名。public是公共组件(也是表格),当点击服务名的时候调用StorageServer方法,我将这个服务名保存到vuex中,起先我是直接保存为数组,后来发现以后如果获取到分支之后,分支如何和服务名建立关系,所以此处我使用let声明了一个对象,对面里面保存了服务名和分支名,起先默认是空的。除此之外为了一个服务只保存一次,我将vuex里面中指循环出来,并将服务名保存到一个新的数组中,然后判断点击的服务名是否在这个数组中,如果不在添加进去。

<template>  <div>    <div id="test">      <el-row>        <el-button class="button-style" type="primary" v-for='(server,index) in servicelist' :key="server.id" @click="StorageServer(server.title)">{{server.title}}</el-button>      </el-row>    </div>    <public />    </div></template><script>    export default {      name: "Caibao",      data() {        return {          servicelist: [],        }      },      created() {        this.GetServiceList();      },      methods: {        GetServiceList() {          // console.log(this.$route)          this.$http.ServiceList(this.$route.params.userId)            .then(res => {              this.servicelist = res;              // console.log(this.servicelist)            }).catch(err => {            console.log(err)          })        },        StorageServer(servername) {              var  StoreService = [];              let ServerNameAndBanrch = {'servername':"",'branch':null};              this.$store.state.ServerNameAndBanrch.forEach(function (item,index) {    #这里我使用for循环的方式将vuex值循环出来,然后将服务名追加到                                                                                       #新的数组,如果新增的服务名不在这里,使用dispatc提交到vuex中。                StoreService.push(item.servername)              });              if(StoreService.indexOf(servername)> -1) return;              ServerNameAndBanrch.servername = servername;              this.$store.dispatch('addserver',ServerNameAndBanrch);        }    }      }</script>

下来时public组件,数据到放到了vuex,那应该到拿出来了吧。首先还是使用create进行方法在组件创建的时候去vuex中拿一次数据,然后我们应该实时的监听vuex中的值,当新增了新的任务之后,我们要实时的显示到public组件中,所以我使用watch针对vuex中这个数据属性进行了实时的监听,然后把新到的数据显示到页面中。

<script>    export default {      name: "Public",      data() {        return {          input10:'',            tableData: [              /*{              servername: 'zyp',              branch:"master",            },*/            ]        }      },      created() {          if(this.$store.state.ServerNameAndBanrch.length>0){            this.$store.state.ServerNameAndBanrch.map(item =>{              let obj={};              obj.servername = item.servername;              obj.branch = item.branch;              this.tableData.push(obj)            })          }      },      watch:{        '$store.state.ServerNameAndBanrch':{          handler:function () {            this.dataVuex()          },          deep: true        }      },      methods:{        dataVuex(){          console.log(this.$store.state.ServerNameAndBanrch);          this.tableData = [];          if(this.$store.state.ServerNameAndBanrch.length>0){            this.$store.state.ServerNameAndBanrch.map(item =>{              let obj={};              obj.servername = item.servername;              obj.branch = item.branch;              this.tableData.push(obj)            });             console.log(this.tableData)          }        },        /*显示分支:将服务名传递到后端执行shell并返回执行结果*/        ObtainBranch(index,servername){          console.log('test',servername.servername)        },        /*删除选项*/        serverDelete(index,servername){          this.$store.state.ServerNameAndBanrch.splice(index,1)        }      }    }

说了很多,其实真正的功能还没有说到,也就是上述截图中的获取分支,打包,还有重启这几个按钮,这几个按钮的代码没有写,但是使用的技术已经测试通过了,下面使用单独的一篇来进行说明。


针对第一次下前端代码的感悟:

第一次写一定要逻辑清晰,否则就像我一样修修改改很多次。

js中的基本操作一定要熟悉,如对数组,对象的操作。

还有就是router-view的使用,曾经自闭了很多次