• 前端小菜鸡使用Vue+Element笔记(一)


    关于使用Vue+Element的项目简介~

    最近因为项目组缺前端人员,所以自己现学现做页面,先把前后台功能调通 觉得前端可真的是不容易呀哎呀~

    首先记录一下相关的Vue入门的教程:

    vue环境搭建示例:https://blog.csdn.net/mao834099514/article/details/79138484

    vue基本语法了解:https://www.runoob.com/vue2/vue-tutorial.html  

              https://cn.vuejs.org/v2/guide/syntax.html 

    Element组件使用文档:http://element-cn.eleme.io/#/zh-CN/component/installation   这个真的很棒,代码可以直接复制下来用的 都不用自己重新写哈哈哈

    这个是别人写的Element组件综合使用的代码,有兴趣的可以从github上把源码下载下来 在本地跑起来看一看 写的很全很优秀  https://github.com/PanJiaChen/vue-element-admin

    前端项目目录结构:

    其中用于开发的是:src 目录 

    src目录结构:

    assets: 存放图片信息

    components: 存放vue页面信息 例如: hello.vue

    config:  里面是一些关于localStorage的配置

    router: 里面包含的是一些路由的配置

    service: 定义与后台进行交互的方法

    store: 定义一些类似与后台session作用域的变量 可以在整个会话中使用这里面定义的对象

     一、 service目录下的 api.js 文件

    统一封装和后台进行交互的Ajax方法,在 *.vue页面可以直接通过import导入 使用该方法与后台进行交互

    import { Message } from 'element-ui'
    import Vue from 'vue'
    import $ from 'jquery'
    /**
     * 封装的全局ajax请求
     */
    Vue.prototype.baseURL = '/XXX-XXX-service'
    const Http = (url, data, type, contentType) => {
      // 默認為post
      type = (type == null || type == '' || typeof (type) === 'undefined') ? 'post' : type//eslint-disable-line
      // 创建一个promise对象
      var promise = new Promise((resolve, reject) => {
        if (!data) {
          data = {}
        }
        if (!contentType && typeof (contentType) === 'string') {
          data.token = sessionStorage.token
        } else {
          url = url + '?token=' + sessionStorage.token
        }
    
        $.ajax({
          type: type,
          data: data,
          url: Vue.prototype.baseURL + url,
          timeout: 60000,
          dataType: 'json',
          contentType: contentType,
          success: function (res) {
            resolve(res)
          },
          error: function (e) {
            reject(e)
            Message.error({
              'message': '系統錯誤,請稍後再試',
              'duration': '2000',
              'showClose': false
            })
          },
          complete: function (XMLHttpRequest, status) {
            if (status == 'timeout') {//eslint-disable-line
              Message.warning({
                'message': '網路超時,請刷新',
                'duration': '2000',
                'showClose': false
              })
            }
          }
        })
      })
      return promise
    }
    //当指定类型为‘application/json’类型时,传给后台的入参必须为对象 且需要通过 JSON.stringfy(userObj)方法处理后才能被正确读取。 使用示例:hello(userObj)
    export const hello = (params) => {
      return Http('/hello', params, 'post', 'application/json')
    }
    
    //这里未指定参数数据类型 则需要一个一个的指明参数 name = 'zs'; age= '18' 不能以对象的形式传到后台。使用示例: userLogin(name,age)
    export const userLogin = (params) => {
      return Http('/auth/user/login', params, 'post')
    }

    二、存储会话级别变量的定义:store目录下的index.js,mutation.js

    index.js文件 :指定state下有那些属性,之后在任意页面都可以直接使用这里定义的属性 以及对应的属性值。

    import Vue from 'vue'
    import Vuex from 'vuex'
    import mutations from './mutations'
    import actions from './actions'
    import getters from './getters'
    
    Vue.use(Vuex)
    const state = {
      fixnavli: 'other',  //这是给单个数据赋值的示例,之后再当前项目的任意一个页面都能获取到这个变量的值
      loadding: false, // 加载动画
      userInfo: sessionStorage.getItem('userInfo') ? JSON.parse(sessionStorage.getItem('userInfo')) : '', //这是从session中取对象值来给state值 userInfo赋值
      userHasLogin: sessionStorage.getItem('userInfo')
    }
    export default new Vuex.Store({
      state,
      actions,
      getters,
      mutations
    })

    mutation.js文件: 给index.js文件中的state指定的属性定义赋值方法,在页面中可以动态改变state指定的属性对应的值

    export const ADD_NUM = 'ADD_NUM'
    export const FIX_NAVLI = 'FIX_NAVLI'
    export const LOADDING = 'LOADDING'
    export const USER_LOGIN = 'USER_LOGIN'
    export const USER_LOGINOUT = 'USER_LOGINOUT'
    export const USER_LOGIN_TEST = 'USER_LOGIN_TEST'
    export const INPUT_FORM = 'INPUT_FORM'
    import {setStore, getStore} from '../config/mUtils'//eslint-disable-line
    
    export default {
      [ADD_NUM] (state) {
        state.num += 1
      },
      [FIX_NAVLI] (state, name) {
        state.fixnavli = name
      },
      [LOADDING] (state, flag) {
        state.loadding = flag
      },
      [USER_LOGIN_TEST] (state) {
        state.userHasLogin = true
      },
      [USER_LOGIN] (state, userInfo) {
        sessionStorage.setItem('userInfo', JSON.stringify(userInfo))
        state.userHasLogin = true
        state.userInfo = userInfo
      },
      [INPUT_FORM] (state, inputForm) {
        sessionStorage.setItem('inputForm', JSON.stringify(inputForm))
        state.inputForm = inputForm
      },
    }

    三、 router目录下的 路由信息 ,相当于控制前端页面的跳转信息

    import Vue from 'vue'
    import Router from 'vue-router'
    import Home from '@/components/Home.vue'
    import store from '@/store/index' // 引入store文件
    
    Vue.use(Router)
    
    const router = new Router({
      mode: 'history', // 默认是hash模式
      scrollBehavior (to, from, savePosition) { // 在点击浏览器的“前进/后退”,或者切换导航的时候触发。
        // console.log(to) // to:要进入的目标路由对象,到哪里去
        // console.log(from) // from:离开的路由对象,哪里来
        // console.log(savePosition) // savePosition:会记录滚动条的坐标,点击前进/后退的时候记录值{x:?,y:?}
        if (savePosition) {
          return savePosition
        } else {
          if (from.meta.keepAlive) {
            from.meta.savedPosition = document.body.scrollTop
          }
          return {
            x: 0,
            y: to.meta.savedPosition || 0
          }
        }
      },
      routes: [
        {
          path: '/login',
          name: 'login',
          props: {
            'title': '登录'
          },
          component: () => import(/* webpackChunkName: "about" */ '@/components/Login.vue') //请求 /login的时候回跳转到 Login.vue页面
        },
        {
          path: '/mainIndex',
          name: 'mainIndex',
          props: {
            'title': '主页面'
          },
          component: () => import(/* webpackChunkName: "about" */ '@/components/mainIndex.vue')  //表示请求 /mainIndex时会跳转到mainIndex.vue页面
        }
      ]
    })
    
    router.beforeEach(function (to, from, next) {
      clearTimeout(Vue.prototype.loaddTimeout)
      clearTimeout(Vue.prototype.loaddTimeout1)
      Vue.prototype.loaddTimeout1 = setTimeout(function () {
        store.commit('LOADDING', true)// 每次跳转显示加载动画
      }, 10000)
      Vue.prototype.loaddTimeout = setTimeout(function () {
        next({path: '/404', query: { redirecter: to.path }})
      }, 60000)
      var login = store.state.userHasLogin
      if (to.path == '/login') {//eslint-disable-line
        store.commit('USER_LOGINOUT')
        next()
      } else {
        if (login) {
          next()
        } else {
          next({
            path: '/login'
          })
        }
      }
    })
    router.afterEach((to, from) => {
      clearTimeout(Vue.prototype.loaddTimeout)
      clearTimeout(Vue.prototype.loaddTimeout1)
      store.commit('LOADDING', false)
    })
    
    export default router

    四、config目录下的 mUtils.js 文件

    /**
     * 存储localStorage
     */
    export const setStore = (name, content) => {
      if (!name) return
      if (typeof content !== 'string') {
        content = JSON.stringify(content)
      }
      window.localStorage.setItem(name, content)
    }
    
    /**
     * 获取localStorage
     */
    export const getStore = name => {
      if (!name) return
      return window.localStorage.getItem(name)
    }
    
    /**
     * 删除localStorage
     */
    export const removeStore = name => {
      if (!name) return
      window.localStorage.removeItem(name)
    }

     五、components目录下的*.vue页面: 这里包含了开发的绝大部分内容呀!!! 在页面里会调用service包下api.js定义的方法,也会使用store包下的index.js定义的state属性

    <template>
      <div class="sidebar">
        <el-container>
          <el-container>
            <el-aside width="200px">Aside</el-aside>
            <el-container>
              <el-header> <h1>个人資料</h1></el-header>
              <el-container>
                <el-aside width="1000px">
                  <el-row>
                    <div class="grid-content bg-purple">
                      <el-col :span="12">
                        <span>姓名:</span>
                        <el-input placeholder="姓名" v-model="name"  class="filter-item"/>
                      </el-col>
                    </div>
                  </el-row>
                  <el-row>
                      <el-col :span="12" >
                        <div class="grid-content bg-purple">
                          <span>出生日期</span>
                          <el-date-picker v-model="birth"  placeholder="年 / 月  / 日" type="date"/>
                        </div>
                      </el-col>
                  </el-row>
                </el-aside>
              <el-header>
              <el-row>
                <div class="grid-content bg-purple">
                   <el-col :span="9"><el-button type="primary" icon="el-icon-search" @click="query">跳转</el-button></el-col>
                   <el-col :span="9"><el-button type="primary" icon="el-icon-search" @click="nextStep">下一步</el-button></el-col>
                </div>
              </el-row>
            </el-header>
            </el-container>
          </el-container>
        </el-container>
      </div>
    </template>
    
    <script>
    import { mapState, mapMutations } from 'vuex'  //这里是指定需要引用state定义的属性
    import {hello} from '../service/api'   //这里是指定引用自定义的与后台进行交互的方法
    
    export default {
      name: 'mainIndex',
      props: {
        title: String
      },
      data: function () {   
        return {  //这里定义需要用到的变量,在这里申明 也可以赋初始值 定义好后方法中可以使用 this.name给变量重新复制
          name: '',
          birth: '',
          aaaaa: this.fixnavli  //
        }
      },
    
      computed: {
        ...mapState([   //这里申明取出mapState中的值,方法中直接使用this.fixnavli, this.userInfo 便可以调用 (名字一一对应)
          'fixnavli',
          'userInfo',
        ])
      },
      methods: {
        ...mapMutations([  //这里是对state定义的属性赋值的方法,用于随时更新state中的属性对应的属性值,使用方法: this.INPUT_FORM(obj)
          'FIX_NAVLI',   
          'INPUT_FORM'
        ]),
    /** 从这里开始 定义页面中需要用到的方法,方法与方法直接的调用 使用 this.query() */
    // 跳过按钮 query: function () { var data = { code: this.fixnavli, msg: this.fixnavli } data = JSON.stringify(data) hello(data).then(res => { alert('返回:' + res.text) }) }, // 下一步 按钮(转到基本计划页面) nextStep: function () { var inputForm = { //定义inputForm对象,可以是简单的对应,也可以是嵌套的对象! 'currentstep': '1','onlProposalForm': { 'onlProposalForm1': { 'name': this.name, //会自动和 v-model指定的名字对应的值绑定 'birth': this.birth, }, 'onlProposalForm2': { 'areaCode': 'SRHK', 'sex': '0', } } } this.INPUT_FORM(inputForm) //调用更新state中定义的属性对应的值的方法
        //这里进行页面跳转
    this.$router.push({ path: '/login' //跳转到登录页面 }) }, // 初始化页面默认数据 selectInit () { let tmpInputForm = this.inputForm // 取出存入session中的对象,判断是否有数据,如果有就从session中取出inputForm对象中存的数据填充页面 if (tmpInputForm != null && tmpInputForm !== '') { this.age = tmpInputForm.onlProposalForm.onlProposalForm1.age this.birth = tmpInputForm.onlProposalForm.onlProposalForm1.birth } else { this.name = 'zs' //初始化的时候给页面的框赋初始值 this.age = '18' } } , //******* 千万要记得需要被调用的方法必须定义在 methods:{} 这个大框框里面,不然会识别不了的!!! }, mounted () { }, created: function () { this.selectInit() //在刚进入页面的时候,会调用created方法,在里面调用自定义的 selectInit()方法进行页面初始化 } } </script> <style> .el-row { margin-bottom: 20px; } .el-button--primary { color: black; background-color: rgba(121, 121, 152, 0.33); border-color: rgba(121, 121, 152, 0.33); } .el-input { auto; } .el-header, .el-footer { background-color: #B3C0D1; color: #333; } .el-aside { background-color: #D3DCE6; color: #333; } .el-main { background-color: #E9EEF3; color: #333; } </style>

    六、关于代理配置信息(项目目录下/config包下的 index.js)

    'use strict'
    // Template version: 1.3.1
    // see http://vuejs-templates.github.io/webpack for documentation.
    
    const path = require('path')
    
    module.exports = {
      dev: {
    
        // Paths
        assetsSubDirectory: 'static',
        assetsPublicPath: '/',
        proxyTable: {
            '/iModule-proposal-service':{
            target: 'http://localhost:8708',  //这个是后台项目的访问端口号  8708
    
            changeOrigin: true,
            pathRewrite: {
              '^/ii-service': '/ii-service'  //这个是后台项目的访问名字 ii-service
            }
          }
        },
    
        // Various Dev Server settings
        host: 'localhost', // can be overwritten by process.env.HOST
        port: 8088, //这个是当前前端项目启动后的访问端口  can be overwritten by process.env.PORT, if port is in use, a free one will be determined
        autoOpenBrowser: false,
        errorOverlay: true,
        notifyOnErrors: true,
        poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
    
        // Use Eslint Loader?
        // If true, your code will be linted during bundling and
        // linting errors and warnings will be shown in the console.
        useEslint: true,
        // If true, eslint errors and warnings will also be shown in the error overlay
        // in the browser.
        showEslintErrorsInOverlay: false,
    
        /**
         * Source Maps
         */
    
        // https://webpack.js.org/configuration/devtool/#development
        devtool: 'cheap-module-eval-source-map',
    
        // If you have problems debugging vue-files in devtools,
        // set this to false - it *may* help
        // https://vue-loader.vuejs.org/en/options.html#cachebusting
        cacheBusting: true,
    
        cssSourceMap: true
      },
    
      build: {
        // Template for index.html
        index: path.resolve(__dirname, '../dist/index.html'),
    
        // Paths
        assetsRoot: path.resolve(__dirname, '../dist'),
        assetsSubDirectory: 'static',
        assetsPublicPath: '/',
    
        /**
         * Source Maps
         */
    
        productionSourceMap: true,
        // https://webpack.js.org/configuration/devtool/#production
        devtool: '#source-map',
    
        // Gzip off by default as many popular static hosts such as
        // Surge or Netlify already gzip all static assets for you.
        // Before setting to `true`, make sure to:
        // npm install --save-dev compression-webpack-plugin
        productionGzip: false,
        productionGzipExtensions: ['js', 'css'],
    
        // Run the build command with an extra argument to
        // View the bundle analyzer report after build finishes:
        // `npm run build --report`
        // Set to `true` or `false` to always turn it on or off
        bundleAnalyzerReport: process.env.npm_config_report
      }
    }
  • 相关阅读:
    转载 Spring boot中配置事务管理
    Mybatis Plus条件构造器condition动态判断优化
    【转载】 利用p6spy拦截并查看数据库执行操作
    使用P6Spy监控你的Spring boot数据库操作
    【转载】 《SpringBoot2.0 实战》系列-集成Quartz定时任务(持久化到数据库)
    baomidou的dynamic-datasource读写分离实现和加入AOP根据方法名选择库
    @EnableWebMvc 注解会让Swagger无效访问的问题
    RestTemplate发送请求并携带header信息
    Shell/Linux 将一个文件中的每两行合并成一行
    蛋白质印迹法(免疫印迹试验,Western Blot)
  • 原文地址:https://www.cnblogs.com/DFX339/p/9816483.html
Copyright © 2020-2023  润新知