vue中使用el-dialog + axios 實現攔截器

weixin_34308389發表於2018-08-13

1.el-dialog 元件

el-dialog 是element的彈出對話方塊元件,專案中用的element元件庫,需要做一個當cookie超時的時候彈出登入的對話方塊,就用到了el-dialog.

先介紹一下el-dailog元件吧,官網介紹

<template>
    <el-button type="text" @click="dialogFormVisible = true">開啟巢狀表單的 Dialog</el-button>

    <el-dialog title="收貨地址" :visible.sync="dialogFormVisible">
      <el-form :model="form">
        <el-form-item label="活動名稱" :label-width="formLabelWidth">
          <el-input v-model="form.name" auto-complete="off"></el-input>
        </el-form-item>
        <el-form-item label="活動區域" :label-width="formLabelWidth">
          <el-select v-model="form.region" placeholder="請選擇活動區域">
            <el-option label="區域一" value="shanghai"></el-option>
            <el-option label="區域二" value="beijing"></el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogFormVisible = false">確 定</el-button>
      </div>
    </el-dialog>
</template>

<script>
  export default {
    data() {
      return {
        dialogFormVisible: false, // 通過改屬性控制是否彈出對話方塊
        form: {
          name: '',
          region: '',
          date1: '',
          date2: '',
          delivery: false,
          type: [],
          resource: '',
          desc: ''
        },
        formLabelWidth: '120px'
      };
    }
  };
</script>

2.axios

Axios 是一個基於 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中 。中文文件

axios支援的特性:

  • 從瀏覽器中建立 XMLHttpRequests
  • 從 node.js 建立 http請求
  • 支援 PromiseAPI
  • 攔截請求和響應
  • 轉換請求資料和響應資料
  • 取消請求
  • 自動轉換 JSON 資料
  • 客戶端支援防禦 XSRF

重點使用一下攔截請求和響應。

官方示例:

// 新增請求攔截器
axios.interceptors.request.use(function (config) {
    // 在傳送請求之前做些什麼
    return config;
  }, function (error) {
    // 對請求錯誤做些什麼
    return Promise.reject(error);
  });

// 新增響應攔截器
axios.interceptors.response.use(function (response) {
    // 對響應資料做點什麼
    return response;
  }, function (error) {
    // 對響應錯誤做點什麼
    return Promise.reject(error);
  });

3.在根元件中新增攔截器,並引入彈框元件

<template>
  <div id="app">
    <router-view/>
    <el-dialog
      title="登陸提示"
      :visible.sync="dialogVisible"
      center
      width="40%">
      <LoginDialog @submitAfter="submitAfter"/> // 子元件給父元件傳值,子元件使用$emit
    </el-dialog>
  </div>
</template>

<script>
    // 引入彈框元件
import LoginDialog from "@/components/LoginDialog";
export default {
  name: "App",
  components: { LoginDialog },
  data() {
    return {
      dialogVisible: false
    };
  },
  methods: {
      // 正常登入後關閉彈框
    submitAfter() {
      this.$data.dialogVisible = false;
    },
      // 路由元件name不是Login並且 cookie中的status狀態過期,彈出登入彈框
    checkSession() {
      if (this.$route.name !== "Login" && !this.$cookies.get("status")) {
        this.$data.dialogVisible = true;
        return false;
      }
      return true;
    }
  },
  mounted() {
      // 根元件載入就創一個攔截器
    this.$ajax.interceptors.request.use(
      config => {
          // 如果不是登入和退出的介面,就正常響應
        if (config.url.indexOf("login.do") !== -1 || config.url.indexOf("logout.do") !== -1) {
          return config;
          // 如果 定義的路由元件name不是Login並且 cookie中的status狀態過期,進行攔截提示
        } else if (!this.checkSession()) {
          return Promise.reject(new Error("會話過期,請重新登入"));
        }
          // 正常請求,不進行攔截
        return config;
      },
      function(error) {
        return Promise.reject(error);
      }
    );
      // 10s 檢查一次cookie中的status是否過期。過期就進行攔截,並進行彈框。
    setInterval(() => {
      this.checkSession();
    }, 10000);
  }
};
</script>

<style>
</style>

4.彈框元件

<template>
  <el-form :model="ruleForm" status-icon :rules="rulesLogin" ref="ruleForm" label-width="100px" class="loginForm">
    <el-form-item label="使用者名稱" prop="username">
      <el-input v-model="ruleForm.username"></el-input>
    </el-form-item>
    <el-form-item label="密碼" prop="pass">
      <el-input type="password" v-model="ruleForm.pass" auto-complete="off"  @keyup.enter.native="submitForm('ruleForm')"></el-input>
    </el-form-item>
    <el-form-item>
      <span class="searchButton" @click="submitForm('ruleForm')">登 錄</span>
      <span class="searchButton1" @click="resetForm('ruleForm')">重 置</span>
    </el-form-item>
  </el-form>
</template>

<script>
import store from '../store'
import { mapActions } from "vuex";
import { systemUrl } from "./../urlCfg.js";

export default {
  data() {
    return {
        // 表單資料
      ruleForm: {
        pass: "",
        username: ""
      },
        // 表單驗證規則
      rulesLogin: {
        pass: [
          {
            validator: validatePass,
            trigger: "blur"
          }
        ],
        username: [
          {
            validator: checkUsername,
            trigger: "blur"
          }
        ]
      }
    };
  },
  store, // vuex狀態
  methods: {
    ...mapActions(["setUser"]),
      // 提交表單
    submitForm(formName) {
      // 驗證表單
      this.$refs[formName].validate(valid => {
        if (valid) {
      // 傳送請求
          this.$ajax({
            method: "post",
            url: systemUrl.login,
            data: {
              userName: this.$data.ruleForm.username,
              password: this.$data.ruleForm.pass
            }
          })
            .then(({data}) => {
              if (data.message === "success") {
                  this.$data.error = ""
                  // 將登入狀態 寫入cookkie 並設定儲存週期
                  this.$cookies.set("status", "logined", 30 * 60)
                  // 將登入返回的資料儲存到vuex中
                  this.setUser(data.data);
                  this.$message({
                    title: '提示',
                    type: 'success',
                    message: '登入成功!'
                  });
                  // 登入成功後將 通過子元件向父元件傳值,關閉彈框
                  this.$emit("submitAfter");
                  this.$refs[formName].resetFields();
              } else {
                  this.$message({
                    title: '提示',
                    type: 'info',
                    message: '使用者名稱或密碼錯誤!請重新登入!'
                  });
              }
            });
        } else {
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    }
  }
};
</script>
<style lang="scss" scoped>
</style>

上面主要是用了axios的請求攔截,響應攔截同理,官網有介紹。

相關文章