11. vue-router路由和vuex
11.1 vue-router路由基本加载
小案例:在根路径下只显示图片,在/hello下即显示图片又显示helloWorld组件里的内容
简单四步走
- 安装
npm install --save vue-router
- 引用(在你的main.js里)
import router from 'vue-router'
Vue.use(router)
- 配置路由文件,并在vue实例中注入(也是在main.js)
var rt = new router({
routes: [
{
path: '/hello',
component: HelloWorld
}
]
})
new Vue({
el: '#app',
router: rt,
components: { App },
template: '<App/>'
})
这里要注意的是如果你是在index.html之外的页面里使用vue-router,那么你路径设置为path='/'就是以你当前的html页面为根目录,比如在一个member.html里使用<router-view></router-view>,然后你在它的js里写path='/',比如你用的是本地端口,那么就是在localhost:8080/member.html/下使用组件,而不是localhost:8080/,也就是把你的member.html作为首页了,而正常情况下的/根目录其实就是你的首页,因为localhost:8080/index.html,因为index是可以省略的
- 确定视图加载的位置(在App.vue中)
使用
<router-view></router-view>
如:
<template>
<div id="app">
<img src="./assets/logo.png">
<!--也就是说当路径等于/hello的时候下面的<router-view>就会替换成HelloWorld组件里的内容-->
<router-view></router-view>
</div>
</template>
这就是让它在图片下方显示
11.2 vue-router路由的跳转
- 通过给需要跳转的元素加<router-link to="/"></router-link>点击跳转到指定的路径
list.vue
<template>
<ul>
<li>
<router-link to="/helloWorld">hello world</router-link>
</li>
<li>
<router-link to="/helloMeizi">hello meizi</router-link>
</li>
</ul>
</template>
router目录下的index.js
export default new router({
routes: [
{
path: '/helloWorld',
component: HelloWorld
},
{
path: '/helloMeizi',
component: HelloMeizi
}
]
})
通过上面的代码我们点击hello world就会跳转到/helloWorld路径下,同样点击/helloMeizi也是一个道理
- 编程式的导航
router.push(location, onComplete?, onAbort?)
注意:在 Vue 实例内部,你可以通过$router
访问路由实例。因此你可以调用this.$router.push
。
当你点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)。
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path:
const userId = 123
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
同样的规则也适用于 router-link 组件的 to 属性。
11.3 vue-router路由参数的传递
- 必须在路由内加入路由的name
- 必须在path后加/: +传递的参数
export default new router({
routes: [
{
name: 'helloWorld',
path: '/helloWorld/:worldmsg',
component: HelloWorld
},
{
name: 'helloMeizi',
path: '/helloMeizi/:meizimsg',
component: HelloMeizi
}
]
})
传递参数和接收参数看下边代码
<!--方式1 推荐-->
<ul>
<li>
<router-link :to="{name: 'helloWorld',params:{worldmsg:'你好世界'}}">hello world</router-link>
读取参数在HelloWorld组件中通过:$route.params.XXX
这种方式显示的路径为:/helloWorld/你好世界
</li>
<li>
<router-link :to="{name: 'helloMeizi',params:{meizimsg:'你好妹子'}}">hello meizi</router-link>
</li>
</ul>
<!--方式2 不推荐-->
<router-link :to="{path: '/helloWorld',query:{worldmsg:你好世界}}">
hello world
</router-link>
显示的路径为:/helloWorld?name=XX&count=xxx
函数模式
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。
<template>
{{q}} //比如当前是/search?q=5,那么此时就能拿到这个5
</template>
const router = new VueRouter({
routes: [
{ path: '/search', component: SearchUser, props: (route) => ({
q: route.query.q }) }
]
})
然后在组件中
props:['q']
11.4 嵌套路由
let rt = new router({
routes: [
{
path: '/',
component: member,
},
{
path: '/address',
component: address,
children: [
{
// /address/all路径下显示all组件
path: 'all',
component: all
},
{
// /address/form路径下显示form组件
path: 'form',
component: form
}
]
},
]
})
上面代码当路径跳转到/address/all和/address/form的时候,分别显示嵌套的子路由组件all和form
那如果想要在/address路径下显示嵌套的子路由组件该怎么做?
- 给子路由一个空路径
{
path: '/address',
component: address,
children: [
{
//在/address路径下显示嵌套路由组件all
path: '',
component: all
},
]
},
- 通过重定向实现路由跳转
{
path: '/address',
component: address,
children: [
{
//从路径''跳转到all,也就是从/address/ 跳转到 /address/all
path: '',
redirect: 'all'
}
]
},
11.5.1 Axios之get请求详解
axios的简介:
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:
- 从浏览器中创建 XMLHttpRequest
- 从 node.js 发出 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防止 CSRF/XSRF
- 安装
npm install axios
- 引入加载
import axios from 'axios'
- 将axios全局挂载到VUE原型上
Vue.prototype.$http = axios;//这里的$http随便什么名字都可以
- 发出请求 以cnode社区API为例子
<template>
<div class="hello">
<button @click="getDate">点击获取数据</button>
<ul>
<li v-for="item in items">{{item.title}}</li>
</ul>
</div>
</template>
<script>
import axios from 'axios'
Vue.prototype.$http = axios
import Vue from 'vue'
export default {
name: 'HelloWorld',
data () {
return {
items: []
}
},
methods: {
getDate(){
this.$http.get('https://cnodejs.org/api/v1/topics',
{
params: {
page:1,
limit: 10
}
}
)
.then(
(response)=>{
this.items = response.data.data
},
(err)=>{
console.log(err)
}
)
}
}
}
</script>
两种传递参数的形式
axios.get('/user', {
params: {
ID: 12345
}
})
axios.get('/user', {
ID: 12345
})
---------------------------------
axios.get('https://cnodejs.org/api/v1/topics?page=1&limit=15')
使用CNODE社区官方的API为例展开学习
获取主题列表API:https://cnodejs.org/api/v1/topics
参数:page页码
limit 每页显示的数量
11.5.2 Axios之post请求详解
POST传递数据有两种格式:
- formdata ?page=1&limit=48
- xwwwformurlencoded { page: 1,limit: 10 }
在axios中,post请求接收的参数必须是formdata
使用qs插件—qs.stringify
npm i qs
getDate(){
this.$http.post(url,qs.stringify({
page: 1,
limit: 10
}))
.then(
(response)=>{
this.items = response.data.data
},
(err)=>{
console.log(err)
}
)
}
11.6 Vuex之store
用来管理状态,共享数据,在各个组件之间管理外部状态
如何使用?
第一步:在main.js中全局引入vuex,并通过use方法使用它
import Vuex from 'vuex'
Vue.use(Vuex)
第二步: 创建状态仓库(注意必须是Store,state不能改成别的名字),在实例中使用它
var store = new Vuex.Store({
state: {
//这里面是你要共享的数据,在所有组件中都可以访问的
message: 88
}
})
new Vue({
el: '#app',
router,
store, //就相当于store: store
components: { App },
template: '<App/>'
})
第三步:通过this.$sore.state.XXX直接拿到需要的数据
这里通过组件中的计算属性来获取
{{getMessage}}
computed: {
getMessage(){
return this.$store.state.message
}
}
11.7 Vuex的相关操作
vuex状态管理的流程
view———>actions———–>mutations—–>state————>view
在组件中改变全局中的状态
1.通过mutations,里面定义的方法必须传入state
var store = new Vuex.Store({
state: {
message: 88
},
mutations: {
getAdd(state){
return state.message+=1
},
getmul(state){
return state.message-=20
}
}
}
然后在组件中使用
<button @click="sadd">子组件---通过mutations改变全局状态</button>
methods: {
sadd(){
//此处的getAdd是你在mucations中定义的方法名
return this.$store.commit('getAdd')
}
}
2.通过actions修改状态,actions里面要传入context上下文对象
var store = new Vuex.Store({
state: {
message: 88
},
mutations: {
getmul(state){
return state.message-=20
}
},
actions: {
a(context){
context.commit('getmul')
}
}
}
在组件中使用
<button @click="c">子组件---通过actions改变全局状态</button>
methods: {
c(){
return this.$store.dispatch('a')
}
}
通过getters可以对你全局状态中的数据做限制,比如让它操作点击按钮累减的时候值不能小于零
var store = new Vuex.Store({
state: {
message: 88
},
getters: {
e(state){
return state.message>0 ? state.message : 0
}
}
})
在组件中使用
{{getMessage}}
computed: {
getMessage(){
return this.$store.state.message
}
}
注意:actions提交的是mutation,而不是直接变更状态
actions可以包含异步操作,但是mutation只能包含同步操作
actions: {
a(context){
setTimeout(()=>{
context.commit('getmul')
},2000)
}
}
最后在你的src文件下新建一个state文件,里面一个index.js将你所有的状态相关的代码写在这里面,然后导出,在main.js里面引入一下