vue学习4

vue学习4,第1张

文章目录 配置代理方法一:Vue.config.jsApp.vue 方法二:Vue.config.jsAPP.vue github案例App.vueSearch.vueList.vueVue-resourcemain.js 插槽默认插槽具名插槽作用域插槽 Vuexvuex理解求和案例_纯vue版本Vuex环境求和案例_Vuex版本 Getters和四种map方法多组件共享数据APP.vueindex.jsCount.vuePerson.vue Vue模块化+命名空间main.jsApp.vueindex.jsperson.vueCount.vue单独拆分 路由路由基本使用main.js bootstrap.cssApp.vueAbout.vueHome.vueindex.js 一般组件,路由组件嵌套路由(多级路由)main.jsindex.jsHome.vueAbout.vueMessage.vueNews.vueApp.vueBanner.vue 路由的query参数+路由命名Detail.vueindex.jsMessage.vueApp.vueAbout.vue params参数路由的props配置router-link的replace属性编程式路由导航Banner.vueDetail.vueMessage.vueindex.js


配置代理

96集:首先,找到文件,然后cmd启动
得到服务器1的地址 http://localhost:5000/students
得到服务器2的地址 http://localhost:5001/cars

下载库npm i axios
引入库import axios from 'axios'

一开始出现了一个错误,跨域:请求发送了,服务器收齐并返回,但是我们获取不到(代理服务器 )

配置好之后要重新启动npm run serve

代理服务器不会把所有的请求都转发给5000,当8080服务器本身就具有请内的内容的时候,public文件中内容是8080服务器所有的不能灵活的控制走不走代理服务器只能配置一个代理,只能转发给5000请求
- 修改了代理服务器,一定要重新开启npm run serve!!! 方法一:

Vue.config.js

里面的内容是在这里找到的 链接https://cli.vuejs.org/config/#devserver-proxy

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
  //开启代理服务器(是因为服务器1 student的端口号时是5000)
  devServer: {
    proxy: 'http://localhost:5000'
  }

})

App.vue
<template>
  <div><button @click="getStudents">获取学生信息</button></div>
</template>

<script>
import axios from "axios";
export default {
  name: "App",
  methods: {
    getStudents() {
      //请求之后返回的是promise值
      axios.get("http://localhost:8080/students").then(
        response => {
          console.log("请求成功了", response.data);
        },
        error => {
          console.log("请求失败了", error.message);
        }
      );
    },
  },
};
</script>


方法二:

可以配置多个代理,且可以灵活的控制请求是否走代理
配置略微繁琐,请求资源时必须加前缀

Vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
  //开启代理服务器(是因为服务器1 student的端口号时是5000)
  /*devServer: {
    proxy: 'http://localhost:5000'
  }*/

  devServer: {
    proxy: {
      // '^/api': {
      //   target: 'http://localhost:5000',
      //   // ws: true,
      //   // changeOrigin: true
      // },
      // '^/foo': {
      //   target: ''
      // }

      '/atguigu':{
        target: 'http://localhost:5000',
        pathRewrite:{'^/atguigu':''},
         ws: true,//用于支持websocket
        changeOrigin: false//用于控制请求头中的host值
      },
      '/demo':{
        target: 'http://localhost:5001',
        pathRewrite:{'^/demo':''},
         ws: true,//用于支持websocket
        changeOrigin: false
      },
    }
  }

})

APP.vue
<template>
  <div><button @click="getStudents">获取学生信息</button>
  
  <button @click="getCars">获取汽车信息</button></div>
 
</template>

<script>
import axios from "axios";
export default {
  name: "App",
  methods: {
    getStudents() {
      
      //前缀加载端口号后面
      axios.get("http://localhost:8080/atguigu/students").then(
        response => {
          console.log("请求成功了", response.data);
        },
        error => {
          console.log("请求失败了", error.message);
        }
      );
    },
getCars(){
    
      axios.get("http://localhost:8080/demo/cars").then(
        response => {
          console.log("请求成功了", response.data);
        },
        error => {
          console.log("请求失败了", error.message);
        }
      );
}

  },
};
</script>



github案例 对所有的进行拆分,记得引入bootstrap.css的写法search进行发送请求把search中的数据在list中显示(全局事件总线/消息订阅与发布/交给app ) 遍历 / 显示加载中


App.vue
<template>
  <div class="container">
    <Search />
    <List />
  </div>
</template>

<script>
import List from "./components/List.vue";
import Search from "./components/Search.vue";

export default {
  name: "App",
  components: {
    List,
    Search,
  },
};
</script>

<style >
</style>
Search.vue
<template>
  <div>
    <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>
  </div>
</template>

<script>
import axios from "axios";
export default {
  name: "Search",
  data() {
    return {
      keyWord: "",
    };
  },
  methods: {
    searchUsers() {
        //请求前更新List数据(发送数据)
      this.$bus.$emit('updateListInfo',{isFirst:false,isLoading:true,errMsg:'',users:[]});
    //怎么在字符串里引用关键字变量,不会将变量认错成字符串(模板字符串)
      axios.get(`https://api.github.com/search/users?q=${this.keyword}`).then(
       
        (response) => {
         //查看收到的数据是什么样的(下面的item就是这么写出来的,还有List组件data中的内容也是靠这个判断的)
          console.log("请求成功了", response.data);
          //不需要加载中那些花里胡哨,只传这一句也是可以的
          // this.$bus.$emit('updateListInfo',{users:response.data.items})
            //请求成功后更新List数据
          this.$bus.$emit('updateListInfo',{isLoading:false,errMsg:'',users:response.data.items});
         
        },
        (error) => {
              //请求失败后更新List数据
          console.log("请求失败了", {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("updateListInfo", (isFirst, isLoading, errMsg, users) => {
      console.log("我是List组件,收到了数据");
      this.isFirst = isFirst;
      this.isLoading = isLoading;
      this.errMsg = errMsg;
      this.users = users;
    });*/
    //接收数据
    this.$bus.$on("updateListInfo", (dataObj) => {
      console.log("我是List组件,收到了数据");
      console.log(dataObj);
      //   this.info = dataObj; 没写的isFirst属性丢了
      this.info = { ...this.info, ...dataObj };//es6语法拼串
    });
  },
};
</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>
Vue-resource

npm i vue-resource

main.js
import Vue from 'vue'
import App from './App.vue'
//引入插件
import vueResource from 'vue-resource'

Vue.config.productionTip = false
//使用插件
Vue.use(vueResource)
const vm = new Vue({
  el: '#app',
  render: h => h(App),
  //全局事件总线
 beforeCreate() {
   Vue.prototype.$bus=this
 },

})

插槽

让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于父组件 >>> 子组件

默认插槽

App.vue

<template>
  <div class="container">
    <Category title="美食" >
      <img src="http://www.kaotop.com/file/tupian/20220516/srJlq0.jpg" alt="">
    </Category>
    <Category title="游戏" >
      <ul>
          <li v-for="(g,index) in games" :key="index">{{g}}</li>
      </ul>
    </Category>
    <Category title="电影" >
      <video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
    </Category>
  
  </div>
</template>

<script>
import Category from "./components/Category.vue";
export default {
  name: "App",
  components: {
   Category,
  },
    data(){
     return{
       foods:['火锅','烧烤','小龙虾','牛排'],
       games:['红色警戒','穿越火线','劲舞团','超级玛丽'],
       films:['教父','拆d专家','你好','盖茨比'],
     }
   },
};
</script>

<style >
.container{
  display: flex;
  justify-content: space-around;
}
img{
  width:100%;
}
video{
  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>
.category{
    background-color: rgb(69, 155, 216);
    width:200px;
    height:300px;
}
h3{
    background-color: orange;
    text-align: center;
}
</style>
具名插槽

App.vue

<template>
  <div class="container">
    <Category title="美食">
      <img
        slot="center"
        src="http://www.kaotop.com/file/tupian/20220516/srJlq0.jpg"
        alt=""
      />
      <a slot="footer" href="http://www.atguigu.com">更多美食</a>
    </Category>
    <Category title="游戏">
      <ul slot="center">
        <li v-for="(g, index) in games" :key="index">{{ g }}</li>
      </ul>
      <div class="foot" slot="footer">
        <a href="http://www.atguigu.com">单机游戏</a>
        <a href="http://www.atguigu.com">网络游戏</a>
      </div>
    </Category>
    <Category title="电影">
      <video
        slot="center"
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
      ></video>
      <!-- <template slot="footer"> 两种都可以 -->
        <template v-slot:footer>
        <div class="foot">
          <a href="http://www.atguigu.com">经典</a>
          <a href="http://www.atguigu.com">热门</a>
          <a href="http://www.atguigu.com">推荐</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: ["教父", "拆d专家", "你好", "盖茨比"],
    };
  },
};
</script>

<style >
.container {
  display: flex;
  justify-content: space-around;
}
img {
  width: 100%;
}
video {
  width: 100%;
}
.foot {
  display: flex;
  justify-content: space-around;
}
h4{
  text-align: center;
}
</style>

Category.vue

<template>
  <div class="category">
      <h3>{{title}}</h3>
      <!-- 定义一个插槽 (挖个坑,等着组件的使用者填空) -->
      <slot name="center">我是一个默认值,当使用者没有传递具体结构时,我会出现1</slot>
       <slot name="footer">我是一个默认值,当使用者没有传递具体结构时,我会出现2</slot>
  </div>
</template>

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

<style>
.category{
    background-color: rgb(69, 155, 216);
    width:200px;
    height:300px;
}
h3{
    background-color: orange;
    text-align: center;
}
</style>
作用域插槽

数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)
App.vue

<template>
  <div class="container">
    <!-- App使用Category组件,atguigu收到的是Category传来的所有,所以atguigu是一个对象 -->
    <Category title="游戏">
      <template scope="atguigu">
        <ul>
          <li v-for="(g, index) in atguigu.liuyue" :key="index">{{ g }}</li>
        </ul>
      </template>
    </Category>

    <Category title="游戏">
      <template scope="{liuyue}">
        <!-- es6解构赋值 把atguigu写成liuyue-->
        <ol>
          <li v-for="(g, index) in liuyue" :key="index">{{ g }}</li>
        </ol>
      </template>
    </Category>
    <Category title="游戏">
      <!-- 写成scope也可以-->
      <template slot-scope="{ msg }">
        <h4>
          <li v-for="(g, index) in msg" :key="index">{{ g }}</li>
        </h4>
      </template>
    </Category>
  </div>
</template>

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

<style >
.container {
  display: flex;
  justify-content: space-around;
}
img {
  width: 100%;
}
video {
  width: 100%;
}
.foot {
  display: flex;
  justify-content: space-around;
}
h4 {
  text-align: center;
}
</style>

Category.vue

<template>
  <div class="category">
    <h3>{{ title }}</h3>
    <!-- 把games传给插槽的使用者 -->
    <slot :liuyue="games" msg="DF">我是一个默认值,当使用者没有传递具体结构时,我会出现1</slot>
    
  </div>
</template>

<script>
export default {
  name: "Category",
  props: ["title"],
  data() {
    return {
      games: ["红色警戒", "穿越火线", "劲舞团", "超级玛丽"],
    };
  },
};
</script>

<style>
.category {
  background-color: rgb(69, 155, 216);
  width: 200px;
  height: 300px;
}
h3 {
  background-color: orange;
  text-align: center;
}
</style>
Vuex vuex理解

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

Vuex Github 网址

什么时候使用Vuex
1.多个组件依赖于同一状态
2.来自不同组件的行为需要变更同一状态

求和案例_纯vue版本

Count.vue

<template>
  <div>
    <h1>{{ sum }}</h1>
    <select v-model="n">
      <!-- 第一种方法:加上冒号,就当成纯粹的js表达式解析,就是数字
      不加冒号,就是字符串,所以加减法的时候3+2="32"(字符串)
      第二种方法: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 {
      sum: 0, //当前的和
      n: 1, //用户选择的数字
    };
  },
  methods: {
    increment() {
      this.sum += this.n;
    },

    decrement() {
      this.sum -= this.n;
    },
    incrementOdd() {
      if (this.sum % 2) {
        this.sum += this.n;
      }
    },
    incrementWait() {
      setTimeout(() => {
        this.sum += this.n;
      }, 500);
    },
  },
};
</script>

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

App.vue

<template>
  <div >
 <Count/>
  </div>
</template>

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

<style >

</style>
Vuex环境


任何一个组件,都可以调用dispatch和Commit,他们都在store身上,Actions,Mutations,State都是对象{}

Vue2==>vuex3
Vue3==>vuex4
首先下载npm i vuex@3

index.js
与components同级创建一个store文件夹,里面有index.js

//该文件用于创建Vuex中最为核心的store

import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)

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


//创建store
const store=new Vuex.Store({

    actions:actions,//对象的key和保存对应值的变量重名了,可以简写
    mutations:mutations,
    state:state,
})

//暴露store,只有暴露了才可以引入
export default store
// export default new Vuex.Store {(...)} 也是可以的

main.js

import Vue from 'vue'
import App from './App.vue'
import store from "./store"
//引入Vuex
//import Vuex from 'vuex'

Vue.config.productionTip=false;
//Vue.use(Vuex)
new Vue({
  el:"#app",
  render:h=>h(App),
  store,
})
直接引入store就行,不需要写store下的index.js注掉并将Vue.use(Vuex)写在index文件是因为在引入store的时候,我们需要先使用Vuex,而且import不论写的顺序在哪,引入store一定是先执行的,所以为了能使用store,我们将Vue.use(Vuex)写在store中,这样就是先使用Vuex,再引入store。 求和案例_Vuex版本

App.vue

<template>
  <div >
   
 <Count/>
  </div>
</template>

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

main.js

import Vue from 'vue'
import App from './App.vue'
//引入插件
import vueResource from 'vue-resource'
//引入Vuex
import Vuex from 'vuex'

import store from './store/index'


Vue.config.productionTip = false
//使用插件
Vue.use(vueResource)

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

index.js

//该文件用于创建Vuex中最为核心的store

import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)

//准备actions,用于响应组件中的动作
//content代表上下文
const actions = {
  /*  jia(context, value) {
        console.log("action中的jia被调用了");
        console.log(context, value);//可以查看一下输出的上下文是什么,以及在哪里找到sum
        context.commit('JIA', value)
    },
    jian(context, value) {
        console.log("action中的jian被调用了");
        console.log(context, value);
        context.commit('JIAN', value)
    },*/
    jiaOdd(context, value) {
        console.log("action中的jiaOdd被调用了");
        if (context.state.sum%2)
            context.commit('JIA', value)
    },
    jiawait(context, value) {
        console.log("action中的jiawait被调用了");

        setTimeout(()=>{
            context.commit('JIA', value)
        },500);
        
    },
}
//准备mutations,用于 *** 作数据(state)
const mutations = {
    JIA(state, value) {
        console.log("mutations中的JIA被调用了");
        state.sum += value;
    },
    JIAN(state, value) {
        console.log("mutations中的JIAN被调用了");
        state.sum -= value;
    },
}
//准备state,用于存储数据
const state = {
    sum: 0, //当前的和
}


//创建store
const store = new Vuex.Store({

    actions: actions,//对象的key和保存对应值的变量重名了,可以简写
    mutations: mutations,
    state: state,
})

//暴露store,只有暴露了才可以引入
export default store
// export default new Vuex.Store {(...)} 也是可以的

Count.vue

<template>
  <div>
    <h1>{{ $store.state.sum }}</h1>
    <select v-model="n">
      <!-- 第一种方法:加上冒号,就当成纯粹的js表达式解析,就是数字
      不加冒号,就是字符串,所以加减法的时候3+2="32"(字符串)
      第二种方法: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, //用户选择的数字
    };
  },
  methods: {
    increment() {
      // this.$store.dispatch("jia", this.n);
      this.$store.commit("JIA", this.n);
    },

    decrement() {
      this.$store.commit("JIAN", this.n);
    },
    incrementOdd() {
     /* if (this.$store.state.num % 2) {
        this.$store.dispatch("jia", this.n);
      }*/
      
      this.$store.dispatch("jiaOdd", this.n);
    },
    incrementWait() {
      setTimeout(() => {
        this.$store.dispatch("jiawait", this.n);
      }, 500);
    },
    mounted() {
      console.log(this);//直接可以查看store,进而判断属性方法如何调用
    },
  },
};
</script>

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


Getters和四种map方法


Count.vue

<template>
  <div>
    <!-- <h1>当前求和为:{{ $store.state.sum }}</h1> -->
    <h1>当前求和为:{{ he }}</h1>
    <h1>当前求和放大10:{{ bigSum }}</h1>
    <!-- <h3>我在{{ $store.state.school }},学习{{$store.state.subject}}</h3> -->
    <h3>我在{{ xuexiao }},学习{{ subject }},这是第二种写法</h3>
    <select v-model="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 { mapGetters, mapState, mapMutations, mapActions } from "vuex";

export default {
  name: "Count",
  data() {
    return {
      n: 1, //用户选择的数字
    };
  },
  methods: {
    /* increment() {
      // this.$store.dispatch("jia", this.n);
      this.$store.commit("JIA", this.n);
    },

    decrement() {
      this.$store.commit("JIAN", this.n);
    },
*/

    /* 方法不写小括号,不代表不传参数,而是默认的事件对象event
   所以使用时,上面的方法要加参数
   借助mapMutations生成对应的方法,方法会调用commit去联系mutations(对象写法)
*/
    ...mapMutations({ increment: "JIA", decrement: "JIAN" }),
    /*数组写法,但是记得上面的方法名字也要改成JIA,否则错误 
  ...mapMutations(['JIA','JIAN']),
  
*/

    /*  incrementOdd() {
 
      this.$store.dispatch("jiaOdd", this.n);
    },
    incrementWait() {
      setTimeout(() => {
        this.$store.dispatch("jiawait", this.n);
      }, 500);
    }
     借助mapActions生成对应的方法,方法会调用dispatch去联系actions(对象写法)
    */
    ...mapActions({ incrementOdd: "jiaOdd", incrementWait: "jiawait" }),
    // ...mapActions(['jiaOdd','jiawait'])
  },
  computed: {
    /*这是程序员自己亲自去写的计算属性
   he() {
      return this.$store.state.sum;
    },*/

    /*1. mapState是一个对象,computed也是一个对象,我们在{}中再写{},是错的
    解决方法,里面写成...{}  es6语法,把每一对key value都展开
    借助mapState生成计算属性,从State中读取属性

    你给他起啥名字,就调用哪个名字(key)值
    */
    ...mapState({ he: "sum", xuexiao: "school", subject: "subject" }),
    /*2.借助mapState生成计算属性(数组写法)保证调用的名字和属性的名字一致
      ...mapState(['sum','school','name']), */
    ...mapGetters(["bigSum"]),
  },

  mounted() {
    const x = mapState({ he: "sum", xuexiao: "school", subject: "subject" });
    console.log("我是验证时候的x,通过查看,我是一个对象", x);
  },
};
</script>

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

index.js

//该文件用于创建Vuex中最为核心的store

import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)

//准备actions,用于响应组件中的动作
//content代表上下文
const actions = {
  /*  jia(context, value) {
        console.log("action中的jia被调用了");
        console.log(context, value);//可以查看一下输出的上下文是什么,以及在哪里找到sum
        context.commit('JIA', value)
    },
    jian(context, value) {
        console.log("action中的jian被调用了");
        console.log(context, value);
        context.commit('JIAN', value)
    },*/
    jiaOdd(context, value) {
        console.log("action中的jiaOdd被调用了");
        if (context.state.sum%2)
            context.commit('JIA', value)
    },
    jiawait(context, value) {
        console.log("action中的jiawait被调用了");

        setTimeout(()=>{
            context.commit('JIA', value)
        },500);
        
    },
}
//准备mutations,用于 *** 作数据(state)
const mutations = {
    JIA(state, value) {
        console.log("mutations中的JIA被调用了",value);
   
        state.sum += value;
    },
    JIAN(state, value) {
        console.log("mutations中的JIAN被调用了");
        state.sum -= value;
    },
}
//准备state,用于存储数据
const state = {
    sum: 0, //当前的和
    school:'尚硅谷',
    subject:"计网",
}
//准备getters,用于将state中的数据进行加工
const getters={
    bigSum(state){
        return state.sum*10;
    }
}

//创建store
const store = new Vuex.Store({

    actions: actions,//对象的key和保存对应值的变量重名了,可以简写
    mutations: mutations,
    state: state,
    getters,
})

//暴露store,只有暴露了才可以引入
export default store
// export default new Vuex.Store {(...)} 也是可以的

main.js 和 App.vue同上

多组件共享数据 APP.vue
<template>
  <div class="container">
    <Count />
    <hr />
    <Person />
  </div>
</template>

<script>
import Count from "./components/Count";
import Person from "./components/Person";

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

index.js

就是加了一个ADD_PERSON方法和PersonList属性

import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)

//准备actions,用于响应组件中的动作
const actions = {
    jiaOdd(context, value){
        console.log("actions+jiaOdd被调用了");
        if(state.sum%2){
            context.commit("JIA", value);
        }
    },
    jiawait(context, value){
        console.log("actions+jiawait被调用了");
        context.commit("JIA", value);
    }
}
//准备mutations,用于 *** 作数据state
const mutations = {
    JIA(context, value) {
        console.log("mutations中的JIA被调用了");
        state.sum += value
    },
    JIAN(context, value){
        console.log("mutations中的JIAN被调用了");
        state.sum-=value
    },
    ADD_PERSON(state, value) {
        console.log("mutations中的value(personObj)被调用了");
     state.personList.unshift(value)
    }

}
//准备state,用于存储数据
const state = {
    sum: 0,
    personList:[
		{id:'001',name:'JOJO'}
	],
}

const getters={
    bigSum(state){
        return state.sum*10
    }
}
//创建store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters,
})
Count.vue
<template>
  <div>
    <h1>当前求和为:{{ sum }}</h1>
    <h1>{{ bigSum }}</h1>
    	<h3 style="color:red">Person组件的总人数是:{{personList.length}}</h3>
    <select v-model="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 { mapGetters, mapState, mapMutations, mapActions } from "vuex";
export default {
  name: "Count",
  data() {
    return {
      n: 1,
    };
  },
  methods: {
    ...mapMutations({ increment: "JIA", decrement: "JIAN" }),
    ...mapActions({ incrementOdd: "jiaOdd", incrementWait: "jiawait" }),
  },
  computed: {
    ...mapState([ "sum","personList" ]),
    ...mapGetters(["bigSum"]),
  },
};
</script>

<style>
button {
  margin: 5px;
}
</style>
Person.vue
<template>
  <div>
      <h1>人员列表</h1>
      <h3 style="color:red">Count组件求和为:{{sum}}</h3>
      <input type="text" placeholder="请输入姓名" v-model="name">
      <button @click="add">提交</button>
      <ul>
          <li v-for="p in $store.state.personList" :key="p.id">{{p.name}}</li>
      </ul>
  </div>
</template>

<script>
import {nanoid} from "nanoid"
export default {
name:"Person",
data(){
    return{
        name:"",
    }
},
computed:{
    sum(){
        return this.$store.state.sum
    }
},
methods:{
    add(){
        const personObj={id:nanoid(),name:this.name}
        this.$store.commit("ADD_PERSON",personObj)
        this.name=''
    }
}
}
</script>

<style>

</style>
Vue模块化+命名空间

让代码更好维护,让多种数据分类更加明确

main.js
import Vue from 'vue'
import App from './App.vue'
//引入插件
import vueResource from 'vue-resource'
//引入Vuex
import Vuex from 'vuex'

import store from './store/index'


Vue.config.productionTip = false
//使用插件
Vue.use(vueResource)

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

App.vue
<template>
  <div>
    <Count />
    <Person />
  </div>
</template>

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


index.js
//该文件用于创建Vuex中最为核心的store

import Vuex from 'vuex'
import Vue from 'vue'
import axios from 'axios'
import {nanoid} from 'nanoid'
Vue.use(Vuex)

//求和相关的配置
const countOptions = {
    //开启命名空间
    namespaced: true,
    actions: {
        jiaOdd(context, value) {
            console.log("action中的jiaOdd被调用了");
            if (context.state.sum % 2)
                context.commit('JIA', value)
        },
        jiawait(context, value) {
            console.log("action中的jiawait被调用了");

            setTimeout(() => {
                context.commit('JIA', value)
            }, 500);

        },
    },
    mutations: {
        JIA(state, value) {
            console.log("mutations中的JIA被调用了", value);

            state.sum += value;
        },
        JIAN(state, value) {
            console.log("mutations中的JIAN被调用了");
            state.sum -= value;
        },
    },
    state: {
        sum: 0, //当前的和
        school: '尚硅谷',
        subject: "计网",
    },
    getters: {
        bigSum(state) {
            return state.sum * 10;
        }
    },
}
//人员管理相关的配置
const personOptions = {
    namespaced: true,
    actions: {
        addPersonWang(context, value) {
            //value是person对象,可以log查看一下
            if (value.name.indexOf('王') === 0) {
                context.commit("ADD_PERSON", value)
            } else {
                alert("添加的人必须姓王!");
            }
        },
        //联系服务器要某人名字
        addPersonServer(context){
            axios.get('http://api.uixsj.cn/hitokoto/get?type=social').then(
                response=>{  
                    context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
                },
                error=>{ alert(error.message)}
            )
        }
    },
    mutations: {
        ADD_PERSON(state, value) {
            console.log("mutations中的value(personObj)被调用了");
            state.personList.unshift(value)
        }
    },

    state: {
        personList: [{ id: "001", name: "张三" }],
    },
    getters: {
        //这个地方的state是自己的state,而不是总的state
        firstPersonName(state) {
            return state.personList[0].name;
        }
    },
}

//创建store
export default new Vuex.Store({

    modules: {
        countAbout: countOptions,
        personAbout: personOptions,
    }
})


person.vue

<template>
  <div>
    <h1>人员列表</h1>
    <h3 class="cnt">Count组件的求和为{{ sum }}</h3>
    <h3>列表中第一个人的名字是:{{ firstPersonName }}</h3>
    <input type="text" placeholder="请输入名字" v-model="name" />
    <button @click="add">添加</button>
    <button @click="addWang">添加一个姓王的人</button>
   <button @click="addPersonServer">添加一个人,名字随机</button>
    <ul>
      <li v-for="p in personList" :key="p.id">{{ p.name }}</li>
    </ul>
  </div>
</template>

<script>
import { mapState } from "vuex";
import { nanoid } from "nanoid";
export default {
  name: "Person",
  data() {
    return {
      name: "",
    };
  },
  computed: {
    //这两种写法都可以
    //  ...mapState(["personList","sum"]),
    personList() {
      return this.$store.state.personAbout.personList;
    },
    sum() {
      return this.$store.state.countAbout.sum;
    },
    firstPersonName() {
      return this.$store.getters["personAbout/firstPersonName"];
    },
  },
  methods: {
    add() {
      const personObj = { id: nanoid(), name: this.name };
      console.log(personObj);
      this.$store.commit("personAbout/ADD_PERSON", personObj);
      this.name = "";
    },
    addWang() {
      //commit联系mutation,dispatch联系actions
      const personObj = { id: nanoid(), name: this.name };
      this.$store.dispatch("personAbout/addPersonWang", personObj);
      this.name = "";
    },
    addPersonServer(){
         this.$store.dispatch("personAbout/addPersonServer");
    }
  },
};
</script>

<style>
</style>
Count.vue
<template>
  <div>
    <h1>当前求和为:{{ sum }}</h1>
    <h1>当前求和放大10:{{ bigSum }}</h1>

    <h3>我在{{ school }},学习{{ subject }},这是第二种写法</h3>
    <h3 class="cnt">下方组件的总人数是:{{ personList.length }}</h3>
    <select v-model="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 { mapGetters, mapState, mapMutations, mapActions } from "vuex";

export default {
  name: "Count",
  data() {
    return {
      n: 1, //用户选择的数字
    };
  },
  methods: {
    ...mapMutations("countAbout", { increment: "JIA", decrement: "JIAN" }),
    ...mapActions("countAbout", {
      incrementOdd: "jiaOdd",
      incrementWait: "jiawait",
    }),
  },
  computed: {
    //未开启命名空间 ...mapState({ countAbout:"countAbout",personAbout:"personAbout" }),
    ...mapState("countAbout", ["sum", "school", "subject"]),
    ...mapState("personAbout", ["personList"]),
    ...mapGetters("countAbout", ["bigSum"]),
  },

  mounted() {
    // const x = mapState({ he: "sum", xuexiao: "school", subject: "subject" });
    // console.log("我是验证时候的x,通过查看,我是一个对象", x);
    console.log(this.$store);
  },
};
</script>

<style>
button {
  margin: auto 5px;
}
.cnt {
  background-color: rgb(236, 153, 154);
  width: 300px;
}
</style>
单独拆分

也可以吧person和count单独拆分成.js
注意写法上

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

开启命名空间后,组件读取state数据

//方式一:自己直接读取
this.$store.state.personAbout.list
//方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject']),

开启命名空间后,组件读取state数据

//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])

开启命名空间后,组件中调用dispatch:

//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

开启命名空间后,组件中调用commit:

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

什么是路由?

一个路由就是一组映射关系(key - value)key 为路径,value 可能是 function 或 component(组件)

后端路由:

理解:value 是 function,用于处理客户端提交的请求工作过程:服务器接收到一个请求时,根据请求路径找到匹配的函数来处理请求,返回响应数据

前端路由:

理解:value 是 component(组件),用于展示页面内容工作过程:当浏览器的路径改变时,对应的组件就会显示

路由基本使用

首先把index.html中的bootstrap.css使用打开

注意新建一个router文件夹,把index.js放入

新建一个pages文件夹,把About和Home放入

在路由配置中是routes,component,而不是 routers,components

下载vue-router:npm i vue-router@3

main.js
import Vue from 'vue'
//引入vue-router
import VueRouter from 'vue-router'

import App from './App.vue'
//引入路由文件
import router from './router'
Vue.config.productionTip = false
//应用插件
Vue.use(VueRouter)

const vm = new Vue({
  el: '#app',
  render: h => h(App),
  router,
})

bootstrap.css App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
这个地方是有一个标题内容的
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- 原始html中,我们使用a标签实现页面的跳转 -->
          <!-- <a class="list-group-item active" href="./about.html">About</a>
          <a class="list-group-item" href="./home.html">Home</a> -->

          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link class="list-group-item " active-class="active" to="/about">About</router-link>
          <router-link class="list-group-item"  active-class="active" to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 此处到底展示什么组件,得看用户点击的是哪个导航项 找清这是哪个地方,可以给它加上个样式判断-->
            <!-- 指定组件的呈现位置 -->
            <router-view></router-view>
            
				
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

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


About.vue
<template>
  <h2>我是About的内容</h2>
</template>

<script>
export default {
name:"About",

}
</script>
<style>

</style>
Home.vue
<template>
    <h2>我是Home的内容</h2>
</template>

<script>
export default {
name:"Home",
}
</script>

<style>

</style>
index.js
//该文件用于创建整个应用的路由器
import VueRouter from "vue-router"
//引入组件
import About from "../pages/About"
import Home from "../pages/Home"
//创建并暴露一个路由器
export default new VueRouter({
    routes: [
        {
        path: '/about',
        component: About
    },
    {
        path: '/home',
        component: Home
    },
]
})


一般组件,路由组件

通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载

挂载和销毁在整个过程中都是不断重复的

每个组件都有自己的$route属性,里面存储着自己的路由信息

整个应用只有一个router,可以通过组件的$router属性获取到

一般组件写在components中,路由组件写在pages中

嵌套路由(多级路由)

main.js

直接使用上面的即可

index.js
//该文件用于创建整个应用的路由器
import VueRouter from "vue-router"
//引入组件
import About from "../pages/About"
import Home from "../pages/Home"
import News from '../pages/News'
import Message from '../pages/Message'
//创建并暴露一个路由器
export default new VueRouter({
    routes: [
        //一级路由
        {
            path: '/about',
            component: About
        },
        {
            path: '/home',
            component: Home,
            //二级路由(home的子路由)
            children:[
                {
                path: "news",//二级路由不要加/了
                component: News,
            },
            {
                path: "message",
                component: Message,
            },
        ]
        },
    ]
})
Home.vue
<template>
        <div class="panel-body">
            <div>
              <h2>Home组件内容</h2>
              <div>
                <ul class="nav nav-tabs">
                  <li>
                    <!-- 子级路由,需要带着父级的路径 -->
                    <router-link class="list-group-item" active-class="active" to="/home/news">News</router-link>
                  </li>
                  <li>
                    <router-link class="list-group-item "active-class="active" to="/home/message">Message</router-link>
                  </li>
                </ul>
               <!-- ??? -->
               <router-view></router-view>
               
              </div>
            </div>
          </div>
</template>

<script>
export default {
name:"Home",/*
beforeDestroy(){
  console.log("home组件即将被销毁了");
},
mounted(){
    console.log("home组件挂载完毕",this);
},*/
}
</script>

<style>

</style>
About.vue

用不到,和上面的一样即可

Message.vue
<template>
  <div>
    <ul>
      <li><a href="/message1">message001</a>&nbsp;&nbsp;</li>
      <li><a href="/message2">message002</a>&nbsp;&nbsp;</li>
      <li><a href="/message/3">message003</a>&nbsp;&nbsp;</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "Message",
};
</script>

<style>
</style>
News.vue
<template>
  <div>
    <ul>
      <li>news001</li>
      <li>news002</li>
      <li>news003</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "News",
};
</script>

<style>
</style>
App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
       <Banner/>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- 原始html中,我们使用a标签实现页面的跳转 -->
          <!-- <a class="list-group-item active" href="./about.html">About</a>
          <a class="list-group-item" href="./home.html">Home</a> -->

          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link class="list-group-item " active-class="active" to="/about">About</router-link>
          <router-link class="list-group-item"  active-class="active" to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 此处到底展示什么组件,得看用户点击的是哪个导航项 -->
            <!-- 指定组件的呈现位置 -->
            <router-view></router-view>
            
				
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

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


Banner.vue
<template>
   <div class="page-header"><h2>Vue Router Demo</h2></div>
</template>

<script>
export default {
name:"Banner",
}
</script>

<style>

</style>
路由的query参数+路由命名

跳转的时候带着参数过去

通过这个,才可以把问号??替换掉
这种写法,一点不打扰路由的配置

Detail.vue
<template>
  <ul>
      <li>消息编号:{{$route.query.id}}</li>
      <li>消息标题:{{$route.query.title}}</li>
  </ul>
</template>

<script>
export default {
    name:"Detail",
    mounted(){
        //得到组件相关的路由信息
        console.log("我是detail中输出的",this.$route);
    }

}
</script>

<style>

</style>
index.js
//该文件用于创建整个应用的路由器
import VueRouter from "vue-router"
//引入组件
import About from "../pages/About"
import Home from "../pages/Home"
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail"
//创建并暴露一个路由器
export default new VueRouter({
    routes: [
        //一级路由
        {
            name:"guanyu",
            path: '/about',
            component: About
        },
        {
            path: '/home',
            component: Home,
            //二级路由(home的子路由)
            children:[
                {
                path: "news",//二级路由不要加/了
                component: News,
            },
            {
                path: "message",
                component: Message,
                children:[
                    {  name:"xiangqing",
                        path:'detail',
                        component:Detail,
                    }
                ]
            },
        ]
        },
    ]
})


先把detail中的内容,使用 给呈现出来
先使用普通的路由,再使用特殊的

Message.vue
<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
          <!--跳转路由携带query参数,to的字符串写法 模板字符串混着js的东西 -->
        <!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{ m.title }}</router-link>&nbsp; -->
             <!--跳转路由携带query参数,to的对象写法 模 -->
             <router-link :to="{
                 path:'/home/message/detail', //(要用单引号,双引号会出错,因为外面有一个双引号了
                 //name:'xiangqing',//找到她的名字,呼唤她(path 和name写一个就行)
                 query:{
                     id:m.id,
                     title:m.title
                 },
             }">
                {{m.title}}
             </router-link>
             

      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: "Message",
  data() {
    return {
      messageList: [
        { id: "001", title: "消息001000" },
        { id: "002", title: "消息002" },
        { id: "003", title: "消息003" },
      ],
    };
  },
};
</script>

<style>
</style>
App.vue
<template>
  <div>
    <div class="row">
      <div class="col-xs-offset-2 col-xs-8">
       <Banner/>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-2 col-xs-offset-2">
        <div class="list-group">
          <!-- 原始html中,我们使用a标签实现页面的跳转 -->
          <!-- <a class="list-group-item active" href="./about.html">About</a>
          <a class="list-group-item" href="./home.html">Home</a> -->

          <!-- Vue中借助router-link标签实现路由的切换 -->
          <router-link class="list-group-item " active-class="active" :to="{path:'/about'}">About</router-link>
           <router-link class="list-group-item " active-class="active" :to="{name:'guanyu'}">About</router-link>
          <router-link class="list-group-item"  active-class="active" to="/home">Home</router-link>
        </div>
      </div>
      <div class="col-xs-6">
        <div class="panel">
          <div class="panel-body">
            <!-- 此处到底展示什么组件,得看用户点击的是哪个导航项 -->
            <!-- 指定组件的呈现位置 -->
            <router-view></router-view>
            
				
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Banner from "./components/Banner.vue"
export default {
  name: "App",
  components:{
    Banner,
  }
};
</script>
About.vue
<template>
  <h2>我是About的内容</h2>
</template>

<script>
export default {
name:"About",
beforeDestroy(){
  console.log("about组件即将被销毁了");
},
mounted(){
    console.log("about组件挂载完毕",this);
    //验证一下router是一样的,但是route不是
    window.aboutRoute=this.$route
      window.aboutRouter=this.$router

},
}
</script>

<style>

</style>
params参数

需要修改的地方

路由声明的地方(使用占位符)
{
	path:'/home',
	component:Home,
	children:[
		{
			path:'news',
			component:News
		},
		{
			component:Message,
			children:[
				{
					name:'xiangqing',
					path:'detail/:id/:title', //使用占位符声明接收params参数
					component:Detail
				}
			]
		}
	]
}

Message传递参数的时候
<!-- 跳转并携带params参数,to的字符串写法 -->
<router-link :to="`/home/message/detail/${m.id}/${m.title}`">跳转</router-link>
				
<!-- 跳转并携带params参数,to的对象写法 -->
<router-link 
	:to="{
		name:'xiangqing',
		params:{
		   id:m.id,
           title:m.title
		}
	}"
>跳转</router-link>

路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!

Detail接收参数:
$route.params.id
$route.params.title

Message.vue

<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
          <!--跳转路由携带query参数,to的字符串写法 模板字符串混着js的东西 -->
        <!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{ m.title }}</router-link>&nbsp; -->
             <!--跳转路由携带query参数,to的对象写法 模 -->
          
             <router-link :to="{
                name:'xiangqing',//使用params,一定用的是name,不能用path
                 params:{
                     id:m.id,
                     title:m.title
                 },
             }">
                {{m.title}}
             </router-link>
             

      </li>
    </ul>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: "Message",
  data() {
    return {
      messageList: [
        { id: "001", title: "消息001000" },
        { id: "002", title: "消息002" },
        { id: "003", title: "消息003" },
      ],
    };
  },
};
</script>

<style>
</style>

Detail.vue
自行更改,只需要把上一个query全部替换为params
index.js
自己更改吧,只需要加上第一步的占位符

路由的props配置

Message.vue
可以直接使用上面的 ,需要注意的是,query参数和params参数的更替。
index.js

//该文件用于创建整个应用的路由器
import VueRouter from "vue-router"
//引入组件
import About from "../pages/About"
import Home from "../pages/Home"
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail"
//创建并暴露一个路由器
export default new VueRouter({
    routes: [
        //一级路由
        {
            name: "guanyu",
            path: '/about',
            component: About
        },
        {
            path: '/home',
            component: Home,
            //二级路由(home的子路由)
            children: [
                {
                    path: "news",//二级路由不要加/了
                    component: News,
                },
                {
                    path: "message",
                    component: Message,
                    children: [
                        {
                            name: "xiangqing",
                            path: 'detail/:id/:title',//占位符
                           
                            component: Detail,
                            /*props的第一种写法,值为对象,
                            该对象中的所有key-value都会以props的形式传给Detail组件
                            props: { a: 999, b: "liuyue" }
                            */
                            /*2.值为布尔值,
                            若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件
                            path: 'detail',
                             props:true,
                            */
                           /*3.值为函数*/
                           props($route){
                               return{
                                   id:$route.params.id,
                                   title:$route.params.title
                                   /*如果Message中使用的query传值,那么这个地方可以更正为
                                    id:$route.query.id,
                                   title:$route.query.title
                                   */
                               }
                           },
                           /* 
                           解构赋值
                              props({query}){
                               return{
                                   id:query.id,
                                   title:query.title
                               }
                           }
                           
                           解构赋值的连续写法
                           props({query:{id,title}}){
                               return{
                                   id:id,
                                   title:title
                               }
                           }
                           */
                           
                           
                        }
                    ]
                },
            ]
        },
    ]
})


Detail.vue

<template>
  <ul>
      <li>消息编号:{{$route.params.id}}</li>
      <li>消息标题:{{$route.params.title}}</li>
      <li>a:{{a}}</li>
      <li>b:{{b}}</li>
       <li>消息编号:{{id}}</li>
      <li>消息标题:{{title}}</li>
  </ul>
</template>

<script>
export default {
    name:"Detail",
    props:['a','b',"id","title"],
    mounted(){
        //得到组件相关的路由信息
        console.log(this.$route);
    }

}
</script>

router-link的replace属性
作用:控制路由跳转时 *** 作浏览器历史记录的模式浏览器的历史记录有两种写入方式:push和replace,其中push是追加历史记录,replace是替换当前记录。路由跳转时候默认为push方式开启replace模式:News
4.加上了replace属性之后,点击某一个,他不会在历史记录里留下她的上一个,也就是说直接把上一个链接替换掉,没办法返回到上一个页面

编程式路由导航

不借助router-link的导航
注意,我将所有的params都换成了query

Banner.vue
<template>
  <div class="page-header">
    <h2>Vue Router Demo</h2>

    <button @click="back">后退</button>
    <button @click="forward">前进</button>
    <button @click="test">测试一下go</button>
  </div>
</template>

<script>
export default {
  name: "Banner",
  methods:{
     back(){
      //   console.log(this.$router);//还是在原型里面
      this.$router.back()
     },
     forward(){
           this.$router.forward()
     },
     test(){
        //往前走几步
        this.$router.go(3)
     }
  }
};
</script>

<style>
</style>
Detail.vue
<template>
  <ul>
      <li>消息编号:{{$route.query.id}}</li>
      <li>消息标题:{{$route.query.title}}</li>
      <li>a:{{a}}</li>
      <li>b:{{b}}</li>
       <li>消息编号:{{id}}</li>
      <li>消息标题:{{title}}</li>
  </ul>
</template>

<script>
export default {
    name:"Detail",
    props:['a','b',"id","title"],
    mounted(){
        //得到组件相关的路由信息
        console.log(this.$route);
    }

}
</script>

<style>

</style>
Message.vue
<template>
  <div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        

        <router-link
          :to="{
            name: 'xiangqing', //使用params,一定用的是name,不能用path
            query: {
              id: m.id,
              title: m.title,
            },
          }"
        >
          {{ m.title }}
        </router-link>
        <button @click="pushShow(m)">push查看</button>
        <button @click="replaceShow(m)">replace查看</button>
        
      </li>
    </ul>
    <hr />
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: "Message",
  data() {
    return {
      messageList: [
        { id: "001", title: "消息001000" },
        { id: "002", title: "消息002" },
        { id: "003", title: "消息003" },
      ],
    };
  },

  methods: {
    pushShow(m) {
      // console.log(this.$router);//输出之后,在原形中找到push/replace
      this.$router.push({
        name: "xiangqing", //使用params,一定用的是name,不能用path
        query: {
          id: m.id,
          title: m.title,
        },
      });
    },
    replaceShow(m){
       this.$router.replace({
        name: "xiangqing", //使用params,一定用的是name,不能用path
        query: {
          id: m.id,
          title: m.title,
        },
      });
    }
  },
};
</script>

<style>
</style>
index.js
//该文件用于创建整个应用的路由器
import VueRouter from "vue-router"
//引入组件
import About from "../pages/About"
import Home from "../pages/Home"
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail"
//创建并暴露一个路由器
export default new VueRouter({
    routes: [
        //一级路由
        {
            name: "guanyu",
            path: '/about',
            component: About
        },
        {
            path: '/home',
            component: Home,
            //二级路由(home的子路由)
            children: [
                {
                    path: "news",//二级路由不要加/了
                    component: News,
                },
                {
                    path: "message",
                    component: Message,
                    children: [
                        {
                            name: "xiangqing",
                            path: 'detail',//占位符
                           
                            component: Detail,
                          
                           props($route){
                               return{
                                    id:$route.query.id,
                                   title:$route.query.title
                               }
                           },
                          
                           
                           
                        }
                    ]
                },
            ]
        },
    ]
})


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/940609.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-17
下一篇2022-05-17

发表评论

登录后才能评论

评论列表(0条)

    保存