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
})

 

posted @ 2020-08-18 15:59  全情海洋  阅读(858)  评论(0编辑  收藏  举报