前端学习--Vue部分中

前端学习–Vue部分中

1.Vue中的ajax

前言

如果没有接触过ajax,请先看一下我所写的ajax笔记,如果有不理解的地方请观看相关ajax的课程。

有两种方法可以开代理服务器:

  1. Nginx(学习成本较高)
  2. vue脚手架(推荐)

1.1vue脚手架配置代理服务器解决跨域问题

代理服务器的端口号和我们自己的端口号保持一致。发请求时,直接找代理服务器。

注:更改vue.config.js文件内容,都需要重新运行程序。

方法一

//在vue.config.js中添加配置
   devServer: {
       proxy: 'http://10.1.38.87:9999/'
   }
// 缺点:不能配置多个代理,不能灵活控制是否使用代理。

方法二

//在vue.config.js中添加配置
devServer: {
    proxy: {
      // 请求前缀
      '/api': {
        target: 'http://localhost:9999',
        pathRewrite: { '^/api': '' } //过滤
        // ws: true,    // 用于支持websocket
        // changeOrigin: true   // 控制请求头host值
      },
      '/demo': {
        target: 'http://localhost:9999',
        pathRewrite: { '^/demo': '' }
      }
    }
  }
// 优点:可以配置多个代理,灵活控制请求是否走代理
// 缺点:略微繁琐,且请求端口后要加配置的代理名

案例

<!-- App.vue文件 -->
<template>
  <div>
    <button @click="getInfo">获取学生信息</button>
    <button @click="getInfo2">获取汽车信息</button>
  </div>
</template>

<script>
import axios from "axios";
export default {
  name: "App",
  components: {},
  data() {
    return {};
  },
  methods: {
    getInfo() {
      axios.get("http://localhost:8080/api/students").then(
        (response) => {
          console.log("请求成功", response.data);
        },
        (error) => {
          console.log("请求失败", error.message);
        }
      );
    },
    getInfo2() {
      //这儿get的是代理服务器,然后代理服务器再向后端服务器发送请求
      axios.get("http://localhost:8080/demo/cars").then(
        (response) => {
          console.log("请求成功", response.data);
        },
        (error) => {
          console.log("请求失败", error.message);
        }
      );
    },
  },
};
</script>

1.2github搜索案例

//main.js文件
//引入Vue 
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入
// import vueResource from 'vue-resource'
//关闭Vue的生产提示
Vue.config.productionTip = false

//引用
// Vue.use(vueResource);
//创建vm
new Vue({
    el: '#app',
    render: h => h(App),
    beforeCreate() {
        Vue.prototype.$bus = this
    },
})
<!-- App.vue文件 -->
<template>
  <div class="container">
    <Search></Search>
    <List></List>
  </div>
</template> 

<script>
import Search from "./components/Search.vue";
import List from "./components/List.vue";
export default {
  name: "App",
  components: { Search, List },
  methods: {},
};
</script>
<!-- Search.vue文件 -->
<template> 
  <section class="jumbotron">
    <h3 class="jumbotron-heading">Search Github Users</h3>
    <div>
      <input
        type="text"
        placeholder="enter the name you search"
        v-model="keyword"
      />&nbsp;
      <button @click="searchUsers()">Search</button>
    </div>
  </section>
</template>

<script>
// 如果运用vue-resource插件库就不需要引入axios
import axios from "axios";

export default {
  name: "Search",
  data() {
    return {
      keyword: "",
    };
  },
  methods: {
    searchUsers() {
      this.$bus.$emit("updateListData", {
        isFirst: false,
        isLoading: true,
        errMsg: "",
        users: [],
      });
      // 引用了vue-resource插件库就要写为this.$http.get...
      axios.get(`https://api.github.com/search/users?q=${this.keyword}`).then(
        (response) => {
          console.log("请求成功了", response.data.items);
          this.$bus.$emit("updateListData", {
            isLoading: false,
            errMsg: "",
            users: response.data.items,
          });
        },
        (error) => {
          console.log("请求失败了", error.message);
          this.$bus.$emit("updateListData", {
            isLoading: false,
            errMsg: error.message,
            users: [],
          });
        }
      );
    },
  },
};
</script>

<style>
</style>
<!-- List.vue文件 -->
<template> 
  <div class="row">
    <!-- 展示用户列别 -->
    <div
      v-show="info.users.length"
      class="card"
      v-for="user in info.users"
      :key="user.login"
    >
      <a :href="user.html_url" target="_blank">
        <img :src="user.avatar_url" style="width: 100px" />
      </a>
      <p class="card-text">{{ user.login }}</p>
    </div>
    <!-- 展示欢迎词 -->
    <h1 v-show="info.isFirst">欢迎你!</h1>
    <!-- 展示加载中 -->
    <h1 v-show="info.isLoading">加载中....</h1>
    <!-- 展示错误信息 -->
    <h1 v-show="info.errMsg">{{ info.errMsg }}</h1>
  </div>
</template>

<script>
export default {
  name: "List",
  data() {
    return {
      info: {
        isFirst: true,
        isLoading: false,
        errMsg: "",
        users: [],
      },
    };
  },
  mounted() {
    this.$bus.$on("updateListData", (Obj) => {
      // 防止内容丢失
      this.info = { ...this.info, ...Obj };
    });
  },
};
</script>

<style scoped>
.album {
  min-height: 50rem; /* Can be removed; just added for demo purposes */
  padding-top: 3rem;
  padding-bottom: 3rem;
  background-color: #f7f7f7;
}

.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>

注:在public文件中建立css文件,然后把即将需要引入到vue中的样式文件放在新建立的css文件中。

2.vue-resource插件库

vue-resource插件库了解即可,现在使用axios封装居多,并且vue-resource插件库官方已经不再维护。

下载vue-resource插件库,在vs终端输入npm i vue-resource

具体案例见上方1.2github搜索案例。

3.插槽

3.1默认插槽

<!-- App.vue文件 -->
<template>
  <div class="container">
    <Category title="美食">
      <img src="../public/favicon.png" alt="" />
    </Category>
    <Category title="游戏">
      <ul>
        <li v-for="(items, index) in games" :key="index">{{ items }}</li>
      </ul>
    </Category>
    <Category title="电影">
      <img src="../public/favicon.png" alt="" />
    </Category>
  </div>
</template>

<script>
import Category from "./components/Category.vue";
export default {
  name: "App",
  components: { Category },
  data() {
    return {
      foods: ["火锅", "炸鸡", "汉堡包"],
      games: ["愤怒的小鸟", "穿越火线", "英雄联盟"],
      films: ["《暮光之城》", "《哈利波特》", "《破坏王》"],
    };
  },
  methods: {},
};
</script>

<style scoped>
.container {
  display: flex;
  justify-content: space-around;
}
img {
  width: 100%;
}
</style>
<!-- Category.vue文件 -->
<template>
  <div class="Category">
    <h3>{{ title }}分类</h3>
    <!-- 定义一个默认插槽,等待被使用。 -->
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: "Category",
  props: ["title"],
};
</script>

<style scoped>
.Category {
  width: 150px;
  height: 250px;
  background: aqua;
}

h3 {
  background: rgb(255, 238, 5);
  text-align: center;
}
</style>

3.2具名插槽

<!-- App.vue文件 -->
<template>
  <div class="container">
    <Category title="美食">
      <img slot="center" src="../public/favicon.png" alt="" />
      <a slot="footer" href="" class="foot">点击我</a>
    </Category>
    <Category title="游戏">
      <ul slot="center">
        <li v-for="(items, index) in games" :key="index">{{ items }}</li>
      </ul>
      <div class="foot" slot="footer">
        <a href="">点击我</a>
        <a href="">点击我</a>
      </div>
    </Category>
    <Category title="电影">
      <video
        slot="center"
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
      />
      <!-- 不要使用v-slot写法,因为他只能使用在template标签上 -->
      <template v-slot:footer>
        <div class="foot">
          <a href="">点击我</a>
          <a href="">点击我</a>
        </div>
        <h4>欢迎观看本视频</h4>
      </template>
    </Category>
  </div>
</template>

<script>
import Category from "./components/Category.vue";

export default {
  name: "App",
  components: { Category },
  data() {
    return {
      foods: ["火锅", "炸鸡", "汉堡包"],
      games: ["愤怒的小鸟", "穿越火线", "英雄联盟"],
      films: ["《暮光之城》", "《哈利波特》", "《破坏王》"],
    };
  },
  methods: {},
};
</script>

<style scoped>
.container,
.foot {
  display: flex;
  justify-content: space-around;
}

img {
  width: 100%;
}

video {
  width: 100%;
}

h4 {
  text-align: center;
}
</style>
<!-- Category.vue文件 -->
<template>
  <div class="Category">
    <h3>{{ title }}分类</h3>
    <!-- 定义一个具名插槽,等待被使用 -->
    <slot name="center"></slot>
    <slot name="footer"></slot>
  </div>
</template>

<script>
export default {
  name: "Category",
  props: ["title"],
};
</script>

<style scoped>
.Category {
  width: 150px;
  height: 250px;
  background: pink;
}

h3 {
  background: plum;
  text-align: center;
  color: white;
}
</style>

3.3作用域插槽

<!-- App.vue文件 -->
<template>
  <div class="container">
    <Category title="游戏">
      <!-- 之前的scope已经废弃,要使用slot-scope -->
      <template slot-scope="games">
        <ul>
          <li v-for="(items, index) in games.games" :key="index">
            {{ items }}
          </li>
        </ul>
      </template>
    </Category>
    <Category title="游戏">
      <template slot-scope="games">
        <ol>
          <li v-for="(items, index) in games.games" :key="index">
            {{ items }}
          </li>
        </ol>
      </template>
    </Category>

    <Category title="游戏">
      <!-- 第二种写法 -->
      <template slot-scope="{ games }">
        <h4 style="color: red" v-for="(items, index) in games" :key="index">
          {{ items }}
        </h4>
      </template>
    </Category>
  </div>
</template>

<script>
import Category from "./components/Category.vue";

export default {
  name: "App",
  components: { Category },
  data() {
    return {};
  },
  methods: {},
};
</script>

<style slot-scoped>
.container,
.foot {
  display: flex;
  justify-content: space-around;
}

img {
  width: 100%;
}

h4 {
  text-align: center;
}
</style>
<!-- Category.vue文件 -->
<template>
  <div class="Category">
    <h3>{{ title }}分类</h3>
    <!-- 定义一个作用域插槽,等待被使用 -->
    <slot :games="games"></slot>
  </div>
</template>

<script>
export default {
  name: "Category",
  props: ["title"],
  data() {
    return {
      foods: ["火锅", "炸鸡", "汉堡包"],
      games: ["愤怒的小鸟", "穿越火线", "英雄联盟"],
      films: ["《暮光之城》", "《哈利波特》", "《破坏王》"],
    };
  },
};
</script>

<style scoped>
.Category {
  width: 150px;
  height: 250px;
  background: pink;
}
h3 {
  background: plum;
  text-align: center;
  color: white;
}
</style>

4.Vuex

4.1Vuex简介

Vuex是在Vue中实现集中式状态(状态指的就是数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),它也是一种组件间通信的方式,且适用于任意组件间的通信。

4.2Vuex原理图

注:原理图基于纯vue求和案例(见下方)。

在这里插入图片描述

4.3搭建Vuex环境

接下来需要做的是:

  1. 下载Vuex插件

    注:vue2配套的是vuex3,vue3配套的是vuex4,不要下错了。

    下载vuex插件,在vs终端上输入:npm i vuex@3

  2. 使用Vuex插件

  3. 建立store(原因:dispatch和commit都在store身上)

  4. 让所有的vm和vc都可以使用store。

// index.js文件
// store文件夹下的index.js文件,用于创建Vuex中最核心的store
// 注:在src文件夹中建立store文件夹

import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//使用Vuex
Vue.use(Vuex);

//准备actions——用于响应组件中的动作
const actions = {}
//准备mutations——用于操作数据(state)
const mutations = {}
//准备state——用于存储数据
const state = {}

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})
// main.js文件
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'

//引入插件
import vueResource from 'vue-resource'
// 引入store
import store from './store'
//关闭Vue的生产提示
Vue.config.productionTip = false

//引用插件
Vue.use(vueResource);

//创建vm
new Vue({
    el: '#app',
    store,
    render: h => h(App),
    beforeCreate() {
        Vue.prototype.$bus = this
    },
})

4.4getters的使用

  1. 当state中的数据需要经过加工后再使用时,可以使用getters加工。它可以让所有组件都可以拿到加工后的数据,不会像computed一样(computed计算出来的数据只能本组件使用)。

  2. 在index.js文件中追加getters配置。

    // index.js文件
    ......
    const getters = {
        bigSum(state){
            //注:是返回值哦~
            return state.sum * 10
        }
    }
    //创建并暴露store
    export default new Vuex.Store({
        ......
        getters
    })
    
  3. 组件中读取数据

    <h2>当前数据方法后的十倍:{{ $store.getters.bigSum }}</h2>
    

4.5四个map方法的使用

  1. mapState方法:用于帮助我们映射state中的数据为计算属性

    computed: {
        //借助mapState生成计算属性:sum、school、subject(对象写法)
    ...mapState({sum:'sum',school:'school',subject:'subject'}),
        //借助mapState生成计算属性:sum、school、subject(数组写法)
        ...mapState(['sum','school','subject']),
    },
    
  2. mapGetters方法:用于帮助我们映射getters中的数据为计算属性

    computed: {
        //借助mapGetters生成计算属性:bigSum(对象写法)
        ...mapGetters({bigSum:'bigSum'}),
        //借助mapGetters生成计算属性:bigSum(数组写法)
        ...mapGetters(['bigSum'])
    },
    
  3. mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数

    methods:{
        //靠mapActions生成:incrementOdd、incrementWait(对象形式)
    ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
        //靠mapActions生成:incrementOdd、incrementWait(数组形式)
        ...mapActions(['jiaOdd','jiaWait'])
    }
    
  4. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

    methods:{
        //靠mapActions生成:increment、decrement(对象形式)
        ...mapMutations({increment:'JIA',decrement:'JIAN'}),
        //靠mapMutations生成:JIA、JIAN(对象形式)
        ...mapMutations(['JIA','JIAN']),
    }
    

4.6模块化+命名空间

  1. 目的:让代码更好维护,让多种数据分类更加明确。

  2. 修改store.js文件

    const countAbout = {
      namespaced:true,//开启命名空间
      state:{x:1},
      mutations: { ... },
      actions: { ... },
      getters: {
        bigSum(state){
           return state.sum * 10
        }
      }
    }
    
    const personAbout = {
      namespaced:true,//开启命名空间
      state:{ ... },
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        countAbout,
        personAbout
      }
    })
    
  3. 开启命名空间后,组件中读取state数据:

    //方式一:自己直接读取
    this.$store.state.personAbout.list
    //方式二:借助mapState读取:
    ...mapState('countAbout',['sum','school','subject']),
    
  4. 开启命名空间后,组件中读取getters数据:

    //方式一:自己直接读取
    this.$store.getters['personAbout/firstPersonName']
    //方式二:借助mapGetters读取:
    ...mapGetters('countAbout',['bigSum'])
    
  5. 开启命名空间后,组件中调用dispatch

    //方式一:自己直接dispatch
    this.$store.dispatch('personAbout/addPersonWang',person)
    //方式二:借助mapActions:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
  6. 开启命名空间后,组件中调用commit

    //方式一:自己直接commit
    this.$store.commit('personAbout/ADD_PERSON',person)
    //方式二:借助mapMutations:
    ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
    

案例

纯vue求和案例

<!-- App.vue文件 -->
<template>
<Count></Count>
</template>

<script>
import Count from "./components/Count.vue";
export default {
components: { Count },
name: "App",
};
</script>

<style>
</style>
<!-- count.vue案例 -->
<template>
<div>
 <h2>当前求和为:{{ sum }}</h2>
 <select v-model.number="n">
   <option :value="1">1</option>
   <option :value="2">2</option>
   <option :value="3">3</option>
 </select>
 <button @click="increment">+</button>
 <button @click="decrement">-</button>
 <button @click="incrementOdd">当前求和为奇数再加</button>
 <button @click="incrementWait">等一等再加</button>
</div>
</template>

<script>
export default {
name: "Count",
data() {
 return {
   n: 1,
   sum: 0,
 };
},
methods: {
 increment() {
   this.sum += this.n;
 },
 decrement() {
   this.sum--;
 },
 incrementOdd() {
   if (this.sum % 2) {
     this.sum++;
   }
 },
 incrementWait() {
   setTimeout(() => {
     this.sum++;
   }, 500);
 },
},
};
</script>

<style>
button {
margin: 5px;
}
</style>

求和案例(vuex版)

注:vuex基本使用。

<!-- count.vue文件 -->
<template>
<div>
 <h2>当前求和为:{{ $store.state.sum }}</h2>
 <select v-model.number="n">
   <option :value="1">1</option>
   <option :value="2">2</option>
   <option :value="3">3</option>
 </select>
 <button @click="increment(n)">+</button>
 <button @click="decrement(n)">-</button>
 <button @click="incrementOdd(n)">当前求和为奇数再加</button>
 <button @click="incrementWait(n)">等一等再加</button>
</div>
</template>

<script>
export default {
name: "Count",
data() {
 return {
   n: 1,
 };
},
methods: {
 increment() {
   this.$store.commit("JIA", this.n);
 },
 decrement() {
   this.$store.commit("JIAN", this.n);
 },
 incrementOdd() {
   this.$store.dispatch("jiaOdd", this.n);
 },
 incrementWait() {
   this.$store.dispatch("jiaWait", this.n);
 },
},
};
</script>
<style>
button {
margin: 5px;
}
</style>
// index.js文件
// store文件夹下的index.js文件,用于创建Vuex中最核心的store
// 注:在src文件夹中建立store文件夹

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

//准备actions——用于响应组件中的动作
// context上下文 想找什么东西都去上下文
const actions = {
 jia(context, value) {
     context.commit('JIA', value)
 },
 jian(context, value) {
     context.commit('JIAN', value)
 },
 jiaOdd(context, value) {
     if (context.state.sum % 2) {
         if (context.state.sum % 2) {
             context.commit('JIA', value)
         }
     }
 },
 jiaWait(context, value) {
     setTimeout(() => {
         context.commit('JIA', value)
     }, 1000);
 }
}
//准备mutations——用于操作数据(state)
const mutations = {
 // 在mutation中的函数要大写
 JIA(state, value) {
     state.sum += value
 },
 JIAN(state, value) {
     state.sum -= value
 },
}
//准备state——用于存储数据
const state = {
 sum: 0, // 初始值
}

//创建并暴露store
export default new Vuex.Store({
 actions,
 mutations,
 state,
})

求和案例(map方法版)

<!-- count.vue文件 -->
<template>
<div>
 <h2>当前求和为:{{ sum }}</h2>
 <h2>当前数据方法后的十倍:{{ bigSum }}</h2>
 <h2>学校名称:{{ school }}</h2>
 <h2>专业是:{{ subject }}</h2>
 <select v-model.number="n">
   <option :value="1">1</option>
   <option :value="2">2</option>
   <option :value="3">3</option>
 </select>
 <button @click="increment(n)">+</button>
 <button @click="decrement(n)">-</button>
 <button @click="incrementOdd(n)">当前求和为奇数再加</button>
 <button @click="incrementWait(n)">等一等再加</button>
</div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";

export default {
name: "Count",
data() {
 return {
   n: 1,
 };
},
methods: {
 // increment()
 // {
 //       this.$store.commit('JIA', this.n)
 // },
 //   decrement()
 // {
 //       this.$store.commit('JIAN', this.n)
 // },

 //借用mapMutations生成对应的方法,方法中会调用commit去联系mutations。
 //可以应用数组写法,必须前后名字一致。
 // 注:使用这种写法要记得在模板事件中传参
 ...mapMutations({ increment: "JIA", decrement: "JIAN" }),

 //   incrementOdd()
 // {
 //   this.$store.dispatch('jiaOdd',this.n)
 // },
 //   incrementWait()
 // {
 //   setTimeout(() => {
 //  this.$store.dispatch('jiaSet',this.n)
 //   }, 500);
 // },

 //借用mapActions生成对应的方法,方法中会调用dispatch去联系actions。
 ...mapActions({ incrementOdd: "jiaOdd", incrementWait: "jiaSet" }),
},
computed: {
 // 自己亲自手写的计算属性,这里就是举例,不要这样写。
 /* sum() {
   return this.$store.state.sum
 } */

 //借助mapState生成计算属性,从state中读取数据。(对象写法)
 //...mapState({sum:'sum',school:'school',subject:'subject'})

 //借助mapState生成计算属性,从state中读取数据。(数组写法)
 // 注:要和state中的属性名一致
 ...mapState(["sum", "school", "subject"]),

 // ...mapGetters({bigSum:'bigSum'})
 // 要和getters中的函数名一致
 ...mapGetters(["bigSum"]),
},
};
</script>
<style>
button {
margin: 5px;
}
</style>
// indexedDB.js文件
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'

Vue.use(Vuex);
//准备actions-用于响应组件中的动作
const actions = {
 jia(context, value) {
     context.commit('JIA', value)
 },
 jian(context, value) {
     context.commit('JIAN', value)
 },
 jiaOdd(context, value) {
     if (context.state.sum % 2) {
         if (context.state.sum % 2) {
             context.commit('JIA', value)
         }
     }
 },
 jiaSet(context, value) {
     setTimeout(() => {
         context.commit('JIA', value)
     }, 500);
 }
}
//准备mutations-用于操作数据(state)
const mutations = {
 JIA(state, value) {
     state.sum += value
 },
 JIAN(state, value) {
     state.sum -= value
 },
}
//准备state——用于存储数据
const state = {
 sum: 0,
 school: '沈阳师范大学',
 subject: '计算机科学与技术'
}
//逻辑复杂并且还需要不断复用
const getters = {
 bigSum(state) {
     return state.sum * 10
 }
}

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

Vuex案例最终版

<!-- App.vue文件 -->
<template>
  <div>
    <Count></Count>
    <hr />
    <Person></Person>
  </div>
</template>
<script>
import Count from "./components/Count.vue";
import Person from "./components/Person.vue";

export default {
  components: { Count, Person },
  name: "App",
};
</script>

<style>
</style>
// main.js文件
//引入Vue
import Vue from 'vue'
//引入App 
import App from './App.vue'

//引入
import vueResource from 'vue-resource'

import store from './store'
//关闭Vue的生产提示
Vue.config.productionTip = false

//引用
Vue.use(vueResource);

//创建vm
new Vue({
    el: '#app',
    store,
    render: h => h(App),
    beforeCreate() {
        Vue.prototype.$bus = this
    },
})
<!-- person.vue文件 -->
<template>
  <div>
    <h2 style="color: red">上方的sum为{{ sum }}</h2>
    <h2>第一个人的名字为:{{ firstPersonName }}</h2>
    <input value="" placeholder="请输入加入的成员" v-model="name" />
    <button @click="addWang">添加一个姓王的人</button>
    <button @click="add">添加</button>
    <button @click="addPersonServer">增加一个服务器的人</button>
    <ul>
      <li v-for="person in personList" :key="person.id">
        {{ person.name }}
      </li>
    </ul>
  </div>
</template>

<script>
import { nanoid } from "nanoid";

export default {
  name: "Person",
  data() {
    return {
      name: "",
    };
  },
  computed: {
    personList() {
      return this.$store.state.personAbout.personList;
    },
    sum() {
      return this.$store.state.countAbout.sum;
    },
    firstPersonName() {
      // 读取这种带"/"的要用中括号包裹
      return this.$store.getters["personAbout/firstPersonName"];
    },
  },
  methods: {
    add() {
      const newPerson = { id: nanoid(), name: this.name };
      this.$store.commit("personAbout/ADD_PERSON", newPerson);
      this.name = "";
    },
    addWang() {
      const personObj = { id: nanoid(), name: this.name };
      this.$store.dispatch("personAbout/addPersonWang", personObj);
      this.name = "";
    },
    addPersonServer() {
      this.$store.dispatch("personAbout/addPersonServer");
    },
  },
};
</script>
// person.js文件
import axios from "axios"
import { nanoid } from "nanoid"

export default {
    namespaced: true, //开启命名空间
    actions: {
        addPersonWang(context, value) {
            // 限定必须姓王
            if (value.name.indexOf('王') === 0) {
                context.commit('ADD_PERSON', value)
            } else {
                alert('添加的人必须姓王')
            }
        },
        addPersonServer(context) {
            // 一言API
            axios.get('http://localhost:8080/hexuan/?encode=js&=utf-8').then(
                response => {
                    context.commit('ADD_PERSON', { id: nanoid(), name: response.data })
                }
            ),
                error => {
                    alert(error.message)
                }
        }
    },
    mutations: {
        ADD_PERSON(state, value) {
            state.personList.unshift(value)
        }
    },
    state: {
        personList: [{
            id: '001',
            name: '张三'
        }]
    },
    getters: {
        firstPersonName(state) {
            return state.personList[0].name
        }
    },
}
<!-- count.vue文件 -->
<template>
  <div>
    <h2>当前求和为:{{ sum }}</h2>
    <h2>当前数据方法后的十倍{{ bigSum }}</h2>
    <h2>学校名称:{{ school }}</h2>
    <h2>专业是:{{ subject }}</h2>
    <h2 style="color: red">下方的总人数为:{{ personList.length }}</h2>
    <select v-model.number="n">
      <option :value="1">1</option>
      <option :value="2">2</option>
      <option :value="3">3</option>
    </select>
    <button @click="increment(n)">+</button>
    <button @click="decrement(n)">-</button>
    <button @click="incrementOdd(n)">当前求和为奇数再加</button>
    <button @click="incrementWait(n)">等一等再加</button>
  </div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";

export default {
  name: "Count",
  data() {
    return {
      n: 1,
    };
  },
  methods: {
    ...mapMutations("countAbout", { increment: "JIA", decrement: "JIAN" }),
    ...mapActions("countAbout", {
      incrementOdd: "jiaOdd",
      incrementWait: "jiaSet",
    }),
  },
  computed: {
    // 不开启命名空间namespaced这三个值是获取不到的
    // 一定要写好是谁的里面的什么
    ...mapState("countAbout", ["sum", "school", "subject"]),
    ...mapState("personAbout", ["personList"]),
    ...mapGetters("countAbout", ["bigSum"]),
  },
  // 查看整个store
  /* mounted() {
    console.log(this.$store);
  }, */
};
</script>

<style>
button {
  margin: 5px;
}
</style>
// count.js文件
export default {
    namespaced: true, //开启命名空间
    actions: {
        jiaOdd(context, value) {
            if (context.state.sum % 2) {
                if (context.state.sum % 2) {
                    context.commit('JIA', value)
                }
            }
        },
        jiaSet(context, value) {
            setTimeout(() => {
                context.commit('JIA', value)
            }, 500);
        }
    },
    mutations: {
        JIA(state, value) {
            state.sum += value
        },
        JIAN(state, value) {
            state.sum -= value
        },
    },
    state: {
        sum: 0,
        school: '沈阳师范大学',
        subject: '软件工程',
    },
    getters: {
        bigSum(state) {
            return state.sum * 10
        }
    }
}
// vue.config.js文件
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  // 自定义配置
  pages: {
    index: {
      // 入口文件
      entry: 'src/main.js',
    }
  },
  lintOnSave: false,// 关闭语法检查
  // 开启代理服务器
  // 可以配置多个代理,灵活控制请求是否走代理
  // 略微繁琐,且请求端口后要加配置的代理名
  devServer: {
    proxy: {
      '/hexuan': { // 请求前缀
        // 正常用的时候这个地方要写对应接口
        target: 'https://people.opw.cc/hitokoto/',
        pathRewrite: { '^/hexuan': '' }
        // ws: true,    // 用于支持websocket
        // changeOrigin: true   // 控制请求头host值
      },
      '/demo': {
        target: 'http://localhost:9999',
        pathRewrite: { '^/demo': '' }
      }
    }
  }
})
  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值