Vue前端頁面開發


環境搭建

  1. 利用@vue/cli4創建工程,為兼容element-ui選用vue2.x版本

    vue create vue-demo
    
  2. 添加element-ui框架

    cd vue-demo
    vue add element
    

    上述命令會安裝element-ui插件,不用在入口main.js文件配置如下內容:

    import ElementUI from 'element-ui
    import 'element-ui/lib/theme-chalk/index.css'
    
    Vue.use(ElementUI)
    
  3. 安裝axios庫

    npm install axios -S
    

    在入口main.js文件配置axios:

    var axios = require('axios')
    // 設置請求的基本鏈接,如果需要跨域不能直接設置為服務器接口api
    //axios.defaults.baseURL = '/api'
    // 全局注冊axios,之后在組件中通過this.$axios發送請求
    Vue.prototype.$axios = axios
    

創建登錄頁面

  1. 修改App.vue根組件

    <template>
      <div id="app">
        <router-view></router-view>
      </div>
    </template>
    

    同路由相匹配的子組件將在<router-view>標簽渲染

  2. 創建Login.vue組件

    <template>
        <body class = "login_bg">
            <div class = "login_container">
                <el-form ref="LoginForm" :model="LoginForm" label-width="80px">
                     <h2 class = "login_title">登錄</h2>
                     <el-form-item label="用戶名">
                        <el-input v-model="LoginForm.username"></el-input>
                     </el-form-item>
                     <el-form-item label="密碼">
                        <el-input v-model="LoginForm.password"></el-input>
                     </el-form-item>
                     <el-form-item>
                        <el-button type="primary" @click = "login">登錄</el-button>
                        <el-button @click = "goToRegist">注冊</el-button>
                     </el-form-item>
                </el-form>
            </div>
        </body>    
    </template>
    
    <script>
        export default {
            name: 'Login',
            data() { 
                return {
                    LoginForm: {
                        username: '',
                        password: ''
                    }
                }
            },
            methods: {
                // 登錄
                login(){
                    this.$axios.post('/api/login', 
                    `username=${this.LoginForm.username}&password=${this.LoginForm.password}`).then(successResponse => {
                        // 后端發送過來的是 Result 類型數據,判斷 Result.code 即可
                        if(successResponse.data.code === 200){
                            // 觸發 store 中的 login() 方法,將 LoginForm.username 字段傳遞給 store 中的 username
                            this.$store.commit('login', this.LoginForm)
                            var path = this.$route.query.redirect
                            this.$router.replace({path: path === '/' || path === undefined ? '/index' : path})
                        } else {
                            this.$alert(successResponse.data.message, '😔 Failed', {
                                confirmButtonText: '確定'
                            })
    
                        }
                    }).catch(failResponse => {
    
                    })
                },
                // 進入 regist 界面
                goToRegist(){
                    this.$router.replace({path: '/regist'})
                }
            }
        }
    </script>
    
    <style scoped>
        .login_container {
            border-radius: 20px;
            background-clip: padding-box;
            margin: 130px auto;
            width: 400px;
            padding: 35px 65px 15px 0px;
            background: #fff;
            border: 1px solid #cfc9c9;
        }
        .login_title {
            margin: 0px 0px 40px 75px;
            text-align: center;
            color: #505458;
            font-size: 32px;
        }
    </style>
    

    在vue環境中this指向vue實例,但在vue中使用axios發起請求時如果then和catch方法直接傳入非箭頭函數形式的匿名函數時,this將指向undefined。

    第一種解決方案:

    var _this = this
    

    發送請求前保留this引用,后面使用_this訪問vue實例

    第二種解決方案:

    在then或catch方法中使用箭頭函數形式的匿名函數

  3. 使用vuex管理全局狀態

    export default new Vuex.Store({
      state: {
        user: {
          username: window.localStorage.getItem('user') == null ? '' : JSON.parse(window.localStorage.getItem('user')).username
        }
      },
      mutations: {
        login(state, data) {
          state.user = data
          window.localStorage.setItem('user', JSON.stringify(data))
        }
      },
      actions: {
      },
      modules: {
      }
    })
    

    如果狀態變化,通過this.$store.commit方法修改

  4. 配置路由

    const routes = [
      {
        path: '/index',
        name: 'Index',
        component: Index,
        meta: {
          requireAuth: true
        }
      },
      {
        path: '/login',
        name: 'Login',
        component: Login
      }
    ]
    

    如果使用嵌套路由,嵌套路由僅表示組件的父子關系,與URL地址無關

  5. 配置前端路由攔截器

    main.js入口文件設置攔截器:

    router.beforeEach((to, from, next) => {
      if (to.meta.requireAuth) {
        if (store.state.user.username) {
          next()
        } else {
          next({
            path: 'login',
            query: {redirect: to.fullPath}
          })
        }
      } else {
        next()
      }
    }
    )
    

    to表示目標路由對象,form表示源路由對象,next應保證邏輯代碼執行完后被調用一次

跨域設置

代理解決跨域的原理是:瀏覽器的同源策略僅限制瀏覽器與服務器交互,服務器與服務器交互不受同源策略影響

根目錄創建vue.config.js文件,配置如下:

module.exports = {
    devServer: {
      proxy: { // 跨域支持
        "/api": {
          target: "http://localhost:8081", //API服務器的地址(后端)
          changeOrigin: true, // 虛擬的站點需要更管 origin
          pathRewrite: {
            //重寫路徑 比如 '/api/aaa/ccc'對應后端接口 '/aaa/ccc'
            "^/api": "",
          },
        },
      },
    }};

target表示服務器接口地址

pathRewrite會重寫地址,比如上面代碼會將發送到/api/login的請求代理到http://localhost:8081/login。這樣做的好處是只有/api開頭的請求會被代理,這樣可以避免靜態資源被代理

設置完代理后,只有從本機發起的請求(同域名、同端口)會被代理。如果axios的baseurl與前端服務器不同源,則axios發起的請求不會被代理,造成跨域失敗


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM