vue基礎(七),同源策略以及跨域,vuex


 

跨域基礎

跨域:
    1、是什么
        你的目標和你自己現在的位置一樣還是不一樣

        瀏覽器上的同源策略

        特點:
        1、跨域只存在於瀏覽器
        2、不在瀏覽器發請求是不會存在跨域問題的
        3、http請求分為兩大類: 普通http請求(如百度請求)和ajax請求(跨域是出現在ajax請求)
          
    2、在什么地方    
        瀏覽器會跨域 服務器不會
 
    3、什么條件會跨域   
        同源(協議  ip  端口一致)不跨域  
        不同源就跨域(三個中間有一個不一樣就跨域)
        
    
        http://localhost:8080/     -------  》 github    (有得是后台解決了允許跨域,前端如何解決跨域)

    4、解決跨域:前端可以解決、后端解決。一般后端解決比前端解決容易

 

1.如果端口9000的服務向端口8000的端口發送請求,這一定跨域了,此時我們需要在在webpack配置文件中devserer中配置Proxy代理

  async searchAjax(q) {
      try {
        const result = await axios({
          url: "http://localhost:9000/api/users/info",
          method: "get"
        });
        console.log(result.data);
      } catch (error) {
        console.log(error);
      }

 

在webpack配置文件中devserer中配置Proxy代理

   //3. 增加 devServer 配置
   devServer: {
    open: true,     // 自動打開瀏覽器
    compress: true, // 啟動gzip壓縮
    port: 9000,     // 端口號
    quiet:true,
    // proxy:{
    //   // 請求路徑 http://localhost:9000/api/users/info
    //   //api會把http://localhost:9000覆蓋掉
    //   // 代理轉發路徑 http://localhost:8000/api/users/info

    //   // "/api":{ // // target :"http://localhost:8000", //目標路徑 // // pathRewrite: {"^/api" : ""}, //代理會把身份標識去掉替換成空竄 // // changeOrigin:true // // },
    // }
  },

 

配置代理服務器的原理圖

 

二, vuex的核心

 

1、狀態管理是什么:
        Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式,是一個插件。
        它采用集中式存儲管理應用的所有組件的狀態(數據),並以相應的規則保證狀態以一種可預測的方式發生變化。
        我們也可以認為它也是一種組件間通信的方式,並且適用於任意組件

    2、理解:對vue應用中多個組件的共享狀態進行集中式的管理(讀/寫)
        

    3、為什么要有這個(問題):
        1)多個視圖依賴於同一狀態
        2)來自不同視圖的行為需要變更同一狀態
        3)以前的解決辦法
            a.將數據以及操作數據的行為都定義在父組件
            b.將數據以及操作數據的行為傳遞給需要的各個子組件(有可能需要多級傳遞)
        4)vuex就是用來解決這個問題的


    4、什么時候用:
       Vuex 可以幫助我們管理共享狀態,並附帶了更多的概念和框架。這需要對短期和長期效益進行權衡。
        也就是說應用簡單(組件比較少)就不需要使用(但是可以),如果應用復雜,使用就會帶來很大的便捷
        
    

    5、Vuex核心:把所有的共享狀態數據拿出來放在Vuex中進行集中式管理    

        1、安裝vuex
        2、創建單獨的模塊使用vuex 它是一個插件,按照插件使用方式
        3、書寫四個核心對象
        4、暴露模塊
        5、在Vue配置項當中注冊vuex對象,store
        6、在核心對象寫代碼


        優化:
            1、如果用戶再操作的時候就是很簡單的數據更改,那么可以不用分發給actions,直接提交給mutations去更改
            2、頁面上如果數據不想寫的太長,可以利用getters,去計算出來,然后在組件computed當中獲取計算的這個數據
            3、mapActions等
            


        Vuex4個核心概念
        state          代表初始狀態數據    是一個包含n個屬性(不是方法)的對象
        getters           代表計算屬性數據    是一個包含n個計算屬性的方法的對象
        actions        代表用戶行為數據    是一個包含n個用戶行為回調方法的對象,(用來映射組件用戶的行為回調函數)
        mutations      代表直接修改數據的數據  是一個包含n個直接修改狀態數據方法的對象 (用來讓action的行為調用)        
        注意:只能通過mutations的方法去直接修改,也就是說要想寫state數據必須通過mutations
              actions里面是用戶操作的行為回調函數,它的內部可以寫異步和判斷
              mutations里面是直接修改數據的函數數據,它的內部不可以寫異步和判斷

 

1.安裝vuex, npm install vuex --save

2.新建文件夾vuex,文件store.js,

import Vue from 'vue'
import Vuex from 'vuex'
// 申明插件
Vue.use(Vuex)

3.在main.js引入import store from '@/vuex/store', 注冊store

const vm = new Vue({
  el:'#root',
  render: h => h(App),
 store //如果我們聲明使用(注冊)store(vuex),那么每個組件對象都可以通過this.$store拿到我們的store對象
})

 

例子

1.入口文件main.js

import Vue from 'vue'
import App from '@/App'
import store from '@/vuex/store'


Vue.config.productionTip = false

const vm = new Vue({
  el:'#root',
  render: h => h(App),
  store   //如果我們聲明使用(注冊)store(vuex),那么每個組件對象都可以通過this.$store拿到我們的store對象
})

2.app組件

<template>
  <div>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementIfOdd">如果是奇數加{{count}}</button>
    <button @click="incrementAsync">異步加{{count}}</button>
  </div>
</template>

<script>
// 從store中映射action和state,解構方式,供組件使用
import {mapActions,mapState} from 'vuex'
export default {
  name: 'App'
  //數據定義到vuex(store)里面


  // methods:mapActions(['increment','decrement','incrementIfOdd','incrementAsync'])
  methods:{
    //最原始的寫法
    // increment(){
    //   //this.$store.dispatch分發觸發 store對象內部actions內部對應的方法
    //   this.$store.dispatch('increment')
    // },
    // decrement(){
    //   this.$store.dispatch('decrement')
    // },
    // incrementIfOdd(){
    //   this.$store.dispatch('incrementIfOdd')
    // },
    // incrementAsync(){
    //   this.$store.dispatch('incrementAsync')
    // }
      // 使用mapActions簡化methods的寫法
      //1、如果methods方法名稱和store對象actions內部的方法名稱一致,可以使用下面這樣的寫法
      // ...mapActions(['increment','decrement','incrementIfOdd','incrementAsync'])

      //2、如果methods方法的名稱和store對象actions內部的方法名稱不一致,那么就不能使用數組這樣的寫法
      ...mapActions(['decrement','incrementIfOdd','incrementAsync']),
      ...mapActions({'increment':'iincrement'})
  },

  computed:{
    // count(){
    //   return this.$store.state.count
    // }
 ...mapState(['count'])


  }
  




  //之前的,數據是定義在組件內的
  // data(){
  //   return {
  //     count:0
  //   }
  // },
  // methods:{
  //   increment(){
  //     this.count++
  //   },
  //   decrement(){
  //     this.count--
  //   },
  //   incrementIfOdd(){
  //     if(this.count % 2 === 1){
  //       this.count++
  //     }
  //   },
  //   incrementAsync(){
  //     setTimeout(() => {
  //       this.count++
  //     }, 1000);
  //   }
  // }
}
</script>

<style scoped>
</style>

 

store.js

import Vue from 'vue' import Vuex from 'vuex' // 申明插件 Vue.use(Vuex)

const state = {
//是專門用來存(狀態)數據的地方,它是一個包含多個屬性和屬性值的對象
  count:0
}

const mutations = {
//專門用來更新數據的各種方法組成的對象
//這些個方法,必須是直接修改數據的方法, 不能在這些方法內部存在 判斷  循環  異步
  INCREMENT(state){
    state.count++
  },
  DECREMENT(state){
    state.count--
  }
}

const actions = {
//專門用來和組件行為(用戶行為)進行對接的各種方法組成的對象 //還有一個作用,用來對接成功后,告知相應的mutations中的對應方法去修改數據
// context有commit和state屬性

  // increment(context){
  //   //接到用戶的操作請求(用戶分發)之后,提交給相關的修改數據的函數去修改
  //   //在這里可以去寫 if  for   異步
  //   context.commit('INCREMENT')
  // }



//解構方式
  iincrement({commit}){
    //接到用戶的操作請求(用戶分發)之后,提交給相關的修改數據的函數去修改
    //在這里可以去寫 if  for   異步
    commit('INCREMENT')
  },

  decrement({commit}){
    //接到用戶的操作請求(用戶分發)之后,提交給相關的修改數據的函數去修改
    //在這里可以去寫 if  for   異步
    commit('DECREMENT')
  },

  incrementIfOdd({commit,state}){
    //action內部的方法可以if for 異步 但是mutations里面的不行
    if(state.count % 2 === 1){
      commit('INCREMENT')
    }
  },

  incrementAsync({commit}){
    setTimeout(() => {
      commit('INCREMENT')
    }, 1000);
  }
}

const getters = {
//一系列的方法,計算屬性get方法,根據我們state內的數據計算出來用戶要使用的數據
}

//暴露Store
export default new Vuex.Store({
  state,
  mutations,
  getters,
  actions
})

 

三,案例,在vuex中發送ajax請求,main組件獲取vuex的數據

App組件

<template>
  <div class="container">
    <Header></Header>
    <Main></Main>
  </div>
</template>

<script>
import Header from '@/components/Header'
import Main from '@/components/Main'
export default {
  name: '',
  components:{
    Header,
    Main
  }
}
</script>

<style scoped>

</style>

 

header組件

<template>
  <section class="jumbotron">
    <h3 class="jumbotron-heading">Search Github Users</h3>
    <div>
      <input type="text" placeholder="enter the name you search" v-model="searchName" />
      <button @click="search">Search</button>
    </div>
  </section>
</template>

<script> import {mapActions} from 'vuex'
export default {
  name: "",
  data(){
    return {
      searchName:''
    }
  },
  
  methods:{
    // ...mapActions(['search'])

    search(){
      //和store里面的某個actions方法去對應
      //如果傳遞參數只有一個,可以直接傳
      //如果傳遞多個,必須使用對象
      this.$store.dispatch('search',this.searchName)
    }
  }
};
</script>

<style scoped>
</style>

 

main組件

<template>
  <div>
    <h2 v-if="isFirst">歡迎光臨,請輸入關鍵字進行搜索</h2>
    <h2 v-else-if="isLoading">正在搜索中,請稍后</h2>
    <h2 v-else-if="errMsg">請求出錯:{{errMsg}}</h2>
    <div v-else class="row">
      <div class="card" v-for="(user, index) in users" :key="user.userName">
        <a :href="user.userUrl" target="_blank">
          <img :src="user.userImg" style="width: 100px" />
        </a>
        <p class="card-text">{{user.userName}}</p>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
// 從store中映射出state,供組件使用數據
import {mapState} from 'vuex'


export default {
  name: "",
  // 接收state里的數據,mapState()返回的是一個對象,解包對象
  computed:{
   ...mapState(['isFirst','isLoading','errMsg','users'])
  }
  // data(){
  //   return {
  //     isFirst:true,
  //     isLoading:false,
  //     errMsg:'',
  //     users:[]
  //   }
  // },
  // mounted(){
  //   this.$bus.$on('searchAjax',this.searchAjax)
  // },
  // methods:{
  //   searchAjax(q){
  //     //在發送ajax請求之前,讓頁面顯示正在請求中
  //     this.isFirst = false
  //     this.isLoading = true
  //     //就可以根據searchName去發送ajax請求
  //     this.$http({
  //       url:'https://api.github.com/search/us',
  //       method:'get',
  //       params:{
  //         q
  //       }
  //     }).then(response => {
  //       let userList = response.data.items.map(item => {
  //         return {
  //           userName:item.login,
  //           userUrl:item.url,
  //           userImg:item.avatar_url
  //         }
  //       })
  //       this.users = userList
  //       this.isLoading = false  //請求成功拿到數據,顯示用戶信息

  //     }).catch(error => {
  //       this.errMsg = error.statusText
  //       this.isLoading = false //請求失敗拿到錯誤信息,顯示錯誤信息
  //     })
  //   }
  // }
};
</script>

<style scoped>
.card {
  float: left;
  width: 33.333%;
  padding: 0.75rem;
  margin-bottom: 2rem;
  border: 1px solid #efefef;
  text-align: center;
}

.card > img {
  margin-bottom: 0.75rem;
  border-radius: 100px;
}

.card-text {
  font-size: 85%;
}
</style>

 

store.js

import Vue from 'vue'
import Vuex from 'vuex'
// 引入axios
import axios from 'axios'
// 申明插件
Vue.use(Vuex)

const state = {
  isFirst:true,
  isLoading:false,
  errMsg:'',
  users:[]
}
const mutations = {
  REQUESTING(state){
    state.isFirst = false
    state.isLoading = true
  },
  REQUEST_SUCCESS(state,userList){
    state.users = userList
    state.isLoading = false  //請求成功拿到數據,顯示用戶信息
  },
  REQUEST_FAILD(state,error){
    state.errMsg = error.message
    state.isLoading = false //請求失敗拿到錯誤信息,顯示錯誤信息
  }
}
const actions = {
  //{commit}解構
  search(context,q){
    //在發送ajax請求之前,讓頁面顯示正在請求中
    context.commit('REQUESTING')
    //就可以根據searchName去發送ajax請求
    axios({
      url:'https://api.github.com/search/users',
      method:'get',
      params:{
        q
      }
    }).then(response => {
      //返回一個新數組,數組中有個對象
      let userList = response.data.items.map(item => {
        return {
          userName:item.login,
          userUrl:item.url,
          userImg:item.avatar_url
        }
      })
       //請求成功后,提交給mutations,修改state的數據
      context.commit('REQUEST_SUCCESS',userList)
    }).catch(error => {
      //發送請求失敗后,提交給mutations,修改state的數據,改變狀態
      context.commit('REQUEST_FAILD',error)
    })
  }
}
const getters = {}
// 向外暴露store,給main.js
export default new Vuex.Store({
  state,
  mutations,
  actions,
  getters
})

 


免責聲明!

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



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