hristory.pushState({}, '', '/foo')
history.back()
history.go(-1)//回退一个页面
history.go(1)//前进一个页面
history.forward()//等价于go(1)
history.back()//等价于go(-1)
//配置路由相关信息
//先导入vue和vue-router
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
//1. 通过vue.use(插件)来安装插件
Vue.use(Router)
//2. 创建vueRouter对象
const routes = [
//配置路由和组件之间的对应关系
]
const router = new Router({
routes,
})
//3.将router对象传到vue实例中
export default router;
//4.在main.js中使用router
import router from './router/index'
new Vue({
el: '#app',
router,//使用路由对象,简写对象增强写法
render: h => h(App)
})
Home和About 组件
我是About
我是About内容,哈哈哈
const routes = [
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
}
]
首页
关于
{
path: '',
redirect: '/home' //缺省时重新定向为首页
},
添加缺省值,并重定向到/home路径,此时打开页面,直接显示home组件内容。此时页面URL为:(有#,因为此时默认为hash模式)
const router = new Router({
routes,
mode: 'history' //修改模式为history
})
const router = new Router({
//配置路由和组件之间的应用关系
routes,
mode: 'history',//修改模式为history
linkActiveClass: 'active'
})
export default {
name: 'App',
methods:{
homeClick(){
// this.$router.push('./home')
//不想让他返回
this.$router.replace('./home')
console.log('homeClick');
},
aboutClick(){
// this.$router.push('./about')
this.$router.replace('./about')
console.log('aboutClick');
}
}
}
我是user
我是user内容,嘿嘿嘿
用户ID是:{{ userId }}
用户ID是:{{ $route.params.userId }}
该组件定义一个计算属性,通过this.$route.params.userId获取处于激活状态的路由参数userId。
{
path: '/user/:userId',
component: User
}
用户
data(){
return{
userId: 'XXX'
}
},
$route是代表处于激活状态的路由,这里指的也就是
{
path: '/user/:userId',
name: 'User',
}
$router 指的是router对象,也就是
const router = new Router({})
为什么要懒加载:打包时候js太大,页面响应缓慢
懒加载:如果组件模块化了,当路由被访问的时候才开始加载被选中的组件,这样就是懒加载。(需要的时候再加载)
使用 npm run build 命令将之前创建的项目打包,打开dist文件夹,目录结构如下:
· app.xxx.js是我们自己编写的业务代码
· vendor.xxx.js是第三方框架,例如vue/vue-router/axios等
· mainfest.xxx.js是为了打包的代码做底层支持的,一般是webpack帮我们做一些事情
· 除了这三个还多了js文件,分别是创建的组件,因为这些组件是懒加载的所以被分开打包了。
组件懒加载
// import Home from '../components/Home'
// import About from '../components/About'
// import User from '../components/User'
const Home = () => import('../components/Home')
const About = () => import('../components/About')
const User = () => import('../components/User')
在routes里直接使用Home About User
平常在一个home页面中,我们可能需要/home/news和/home/message访问一些内容,一个路由映射一个组件就像后端一个api对应一个controller的一个requestMapping一样,访问两个路由也会分别渲染这两个组件。
{
path: '/home',
component: Home,
children: [
{
path: '',
redirect: 'news'
},
{
path: 'news',
component: HomeNews
},
{
path: 'message',
component: HomeMessage
}
]
},
我是Home
我是Home内容,哈哈哈
新闻
消息
之前的动态路由说的userId也是参数传递的方式的一种,准备新建一个Profile.vue组件,并配置路由映射,添加指定的。
App.vue组件:
档案
profile.vue组件:
我是profile组件
{{ $route.query.name }}
{{ $route.query.age }}
{{ $route.query.height }}
传递参数主要有两种类型:params 和 query
使用代码编写传递数据,使用button代替,并添加点击事件。
UserClick(){
this.$router.push('/User/' + this.userId)
},
profileClick(){
this.$router.push({
path: '/profile',
query:{
name: 'sylvia',
age: 22,
height: 1.62
}
})
}
vue全局对象 .$router 与 main.js 导入的 router 对象是一个对象,也就是我们router/index.js 导出的对象 router 。
main.js:
new Vue({
el: '#app',
router,
render: h => h(App)
})
index.js:
const router = new Router({
routes,
mode: 'history', //修改模式为history
linkActiveClass: 'active'
})
//3.将router对象传到vue实例中
export default router;
this.$route对象是当前处于活跃的路由,有params和query属性可以用来传递参数。
查看vue-router源码,在我们项目中的router/index.js中,vue 对于插件必须要使用Vue.use(Router),来安装插件,也就是执行vue-router的install.js。
其中index.js是入口文件,入口js文件就是导入并执行了install.js文件。
发现:install.js中有注册2个全局组件RouterView和RouterLink,所以我们能使用和组件。
$ router 和 $ route是继承自vue的原型
怎么理解原型?学过Java 的都知道有父类和子类,子类也可以有自己的子类,但是他们都有一个处于最顶层的类Object(所有类的父类)。在Vue中就有那一个Vue类似Object,在java中在Object中定义的方法,所有的类都可以使用可以重写,类似的Vue.prototype(Vue的原型)定义的属性方法,他的原型链上的对象都可以使用,而 $ router 和 $ route 都在Vue的原型链上。
在main.js入口文件中在vue的原型上定义一个方法test,然后在User组件中尝试调用。
//在vue的原型上添加test方法
Vue.prototype.test = function () {
console.log("test")
}
这是用户界面
这里是用户页面的内容。
用户ID是: {{ userId }}
启动项目点击User页面上的按钮,打开浏览器控制台查看日志发现test方法被执行了,而User组件中并未定义test方法,却可以调用。
继续来读install.js,install.js中一开始就将Vue这个类当参数传入了install方法中,并把Vue赋值给_Vue。
Object.defineProperty(Vue.prototype, '$router', {
get () { return this._routerRoot._router }
})
//Object.defineProperty用来定义属性
Object.defineProperty(Vue.prototype, '$route', {
get () { return this._routerRoot._route }
})
Object.defineProperty用来定义属性,以上代码就是给Vue.prototype(Vue原型)添加$ router和$ route属性并给属性赋值,等价于
Vue.prototype.$router = {
get () { return this._routerRoot._router }
}
Vue.prototype.$route = {
get () { return this._routerRoot._route }
}
也就是在Vue的原型上添加 r o u t e r 和 router和 router和route属性,再查看get()返回值this._routerRoot._router
问题:我们经常需要在路由跳转后,例如从用户页面跳转到首页,页面内容虽然可以自己定义,但是只有一个html文件,也只有一个title标签,我们需要改变标题。
可以使用vue的生命周期函数在组件被创建的时候修改title标签内容。
created() {
//创建的时候修改title
document.title = '关于'
}
mounted() {
//数据被挂载到dom上的时候修改title
}
update() {
//页面刷新的时候修改
}
当然不能每个组件去写生命周期函数,如果我们能监听路由的变化(了解路由从哪来往哪里跳转),那我们就能在跳转中修改title标签,这就是导航守卫能做的事情。
修改router/index.js:
/**
* 前置钩子:从from跳转到to
* from 来的路由
* to 要去的路由
*/
router.beforeEach((to,from,next) => {
//从from跳转到to
document.title = to.matched[0].meta.title;
console.log(to);
next() //必须调用,不调用不会跳转
})
router.beforeEach()称为前置钩子(前置守卫),顾名思义,跳转之前做一些处理。
当然每个路由配置上也要加上meta属性,不然就取不到了,为什么要使用matched[0],因为如果你是嵌套路由,没有给子路由添加meta(元数据:描述数据的数据)属性,就会显示undefined,使用matched[0]表示取到匹配的第一个就会找到父路由的meta属性。
const routes = [
{
path: '',
redirect: '/home' //缺省时重新定向为首页
},
{
path: '/home',
component: Home,
meta:{
title: '首页'
},
children: [
{
path: '',
redirect: 'news'
},
{
path: 'news',
component: HomeNews
},
{
path: 'message',
component: HomeMessage
}
]
},
{
path: '/about',
component: About,
meta:{
title: '关于'
}
},
{
path: '/user/:userId',
component: User,
meta:{
title: '用户'
}
},
{
path: '/profile',
component: profile,
meta:{
title: '档案'
}
}
]
前面说了前置守卫router.beforeEach(),相对的应该也存在后置守卫(后置钩子),顾名思义,也就是在跳转之后的回调函数。
/**
* 后置钩子
*/
router.afterEach((to, from) => {
console.log('后置钩子调用了----')
})
路由独享守卫,路由私有的
{
path: '/about',//about 前端路由地址
name: 'About',
component: () => import('@/components/About'),
beforeEnter: (to, from, next) => {
console.log('来自' + from.path + ',要去' + to.path)
next()
},
meta: {
title: '关于'
}
},
组件内的守卫,直接在组件中定义的属性
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
具体信息看官网:vue-router导航守卫
先给Home组件加上created()和destoryed()2个生命周期函数。
在首页和关于组件之间路由跳转的时候,Home组件一直重复创建和销毁的过程,每次创建都是新的Home组件。
需求:当我点击首页消息页面,随后跳转到关于页面,又跳转到首页,此时我希望显示的是首页的消息页面而不是默认的新闻页面。
解决:此时就需要keep-alive来使组件保持状态,缓存起来,离开路由后,Home组件生命周期的destroyed()不会被调用,Home组件不会被销毁。
启动项目,发现 keep-alive 无效。
在跳转关于页面的时候Home组件并没有被销毁,说明keep-alive生效了。仔细查看路由配置发现,/home被默认重定向到了/home/news。所以在访问/home的时候每次出来的都是新闻。
解决:
activated(){
console.log('调用actived')
this.$router.push(this.path)//在活跃的时候将保存的路由给当前路由
},
deactivated(){
console.log('调用actived')
console.log(this.$route.path)
this.path = this.$route.path//变成不活跃状态,将最后的路由保存起来
}
发现还是不行,由于deactivated()调用的时候,此时路由已经跳转,所以不能在此方法中修改路由,因为修改的是to路由。
activated(){
console.log('调用actived')
this.$router.push(this.path)
},
// deactivated(){
// console.log('调用actived')
// console.log(this.$route.path)
// this.path = this.$route.path
// },
beforeRouterLeave(to, from, next) {
console.log(this.$route.path)
this.path = this.$route.path
next()
}
此时问题解决!
我们将包起来,那所有的组件都会缓存,都只会创建一次,如果我们需要某一个组件每次都创建销毁,就需要使用exclude属性。
此时Profile和User组件(这里组件需要有name属性,分别为Profile和User)就被排除在外,每次都会创建和销毁。相对应的也有include属性,顾名思义就是包含,只有选中的才有keep-alive。
注意:如果每次都要复用tabbar,那每次都需要复制粘贴,应该要把tabbar抽离出来。
在components下新建tabbar文件夹,新建TarBar.vue和TabBarItem.vue,TabBarItem组件是在组件TarBar中抽取出来的,可以传入图片和文字(比如首页),所有需要使用插槽代替。
首页
分类
购物车
我的
要实现需要用到路由
- 图片变色:引用两张图片,使用 v-if 和 v-else 来处理图片是否变色,在路由处于活跃的时候,变红色
- 文字变色:给文字绑定动态style,当路由处于活跃的时候,通过 props 传值来设置文字颜色。
首页
分类
购物车
我的
const Home = () => import('../views/home/Home')
const Category = () => import('../views/category/Category')
const Cart = () => import('../views/cart/Cart')
const Profile = () => import('../views/profile/Profile')
Vue.use(Router)
const routes = [
{
path: '',
redirect: '/home'
},
{
path: '/home',
component: Home
},
{
path: '/category',
component: Category
},
{
path: '/cart',
component: Cart
},
{
path: '/profile',
component: Profile
}
]
export default new Router({
routes,
mode: 'history'
})
经常的我们向引入图片文件等资源的时候使用相对路径,诸如…/assets/xxx这样的使用…/获取上一层,如果有多个上层就需要…/…/xxx等等这样不利于维护代码。此时就需要一个能获取到指定目录的资源的就好了。
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'),
'assets': resolve('src/assets'),
'components': resolve('src/components'),
'views': resolve('src/views'),
}
},
import TabBar from "@/components/tabbar/TabBar";
import TabBarItem from "@/components/tabbar/TabBarItem";
简单说Promise是异步编程的一种解决方案。
$.ajax({
success:function(){
...
}
})
如果碰到嵌套网络请求,例如第一次网络请求成功后回调函数再次发送网络请求,这种代码就会让人很难受。
$.ajax({
success:function(){
$.ajax({
...
})
}
})
如果还需要再次网络请求,那么又要嵌套一层,这样的代码层次不分明很难读,也容易出问题。
一般情况下有异步操作时,使用promise对这个异步操作进行封装(解决异步请求冗余这样的问题,promise就是用于封装异步请求的。)
//promise的参数是一个函数(resolve, reject) = {}
//函数的参数resolve, reject本身又是函数
//链式编程
new Promise((resolve, reject) => {})
new Promise((resolve, reject) => {
//第一次网络请求的代码
setTimeout(() => {
resolve()
},2000)
}).then(() => {
//第一次拿到结果的处理代码
console.log('hello world');
return new Promise((resolve, reject) => {
//第二次网络请求的代码
setTimeout(() => {
resolve()
},2000)
})
}).then(() => {
//第二次拿到结果的处理代码
console.log('hello vue');
return new Promise((resolve, reject) => {
//第三次网络请求的代码
setTimeout(() => {
resolve()
},2000)
})
}).then(() =>{
//第三次拿到结果的处理代码
console.log('hello python');
})
调用resolve()就能跳转到then()方法就能执行处理代码,then()回调的返回值又是一个Promise对象。层次很明显,只要是then()必然就是执行处理代码,如果还有嵌套必然就是返回一个Promise对象,这样调用就像java中的StringBuffer的append()方法一样,链式调用。
//将请求与数据处理分离开来
new Promise((resolve, reject) => {
setTimeout(() => {
//成功时调用resolve
resolve('hello world')
//失败时调用reject
reject('error message')
},1000)
}).then((data) => { //成功时处理
console.log(data);
}).catch(err => { //失败时处理
console.log(err);
})
网络请求:aaa
处理:aaa111
处理:aaa111222
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
},1000)
}).then(res => {
console.log(res);
return new Promise(resolve => {
resolve(res + '111')
})
}).then(res => {
console.log(res);
return new Promise(resolve => {
resolve(res +'222')
})
}).then(res => {
console.log(res);
})
简写Promise.resolve()。
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
},1000)
}).then(res => {
console.log(res);
return Promise.resolve(res + '111')
}).then(res => {
console.log(res);
return Promise.resolve(res + '222')
}).then(res => {
console.log(res);
})
还可以直接省略掉Promise.resolve()
省略掉Promise.resolve
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
},1000)
}).then(res => {
console.log(res);
return res + '111'
}).then(res => {
console.log(res);
return res + '222'
}).then(res => {
console.log(res);
})
如果中途发生异常,可以通过catch()捕获异常,也可以通过throw抛出异常,类似java
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
},1000)
}).then(res => {
console.log(res);
// return Promise.resolve(res + '111') //成功处理
// return Promise.reject('error message') //失败
throw 'error message' //直接抛出异常
}).then(res => {
console.log(res);
return Promise.resolve(res + '222')
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
var isResult1 = false
var isResult2 = false
//请求1
$.ajax({
url: '',
success: function () {
console.log('结果1');
isResult1 = true
handleResult()
}
})
//请求2
$.ajax({
url: '',
success: function () {
console.log('结果2');
isResult2 = true
handleResult()
}
})
function handleResult() {
if(isResult1 && isResult2){
}
}
Promise.all([
// new Promise((resolve, reject) => {
// $.ajax({
// url: 'url1',
// success: function () {
// resolve()
// }
// })
// }),
// new Promise((resolve, reject) => {
// $.ajax({
// url: 'url2',
// success: function () {
// resolve()
// }
// })
// })
new Promise((resolve, reject) => {
setTimeout(() => {
resolve({name: 'sylvia', age: 18})
},1000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve({name: 'xxx', age: 18})
},2000)
})
]).then(results => {
console.log(results);
})
Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
其实最简单理解为,在我们写Vue组件中,一个页面多个组件之间想要通信数据,那你可以使用Vuex
路由 -> 管理的是组件流动
vuex -> 管理的是数据流动
什么状态需要组件间共享?
import Vue from 'vue'
import Vuex from 'vuex'
//1.安装插件
Vue.use(Vuex)
//2.创建对象
const store = new Vuex.Store({
state: {
count: 1000,
}
})
//3.导出
export default store
import Vue from 'vue'
import App from './App'
import router from './router'
import store from "./store";
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
//父组件App.js:
{{ message }}
---------app内容---------
{{ $store.state.count }}
---------hello vuex内容---------
//子组件HelloVue.js:
{{ $store.state.count }}
1. 提取出一个公共的store对象,用于保存在多个组件中共享的状态
2. 将store对象放置在new Vue对象中,这样可以保证在所有的组件中都可以使用到
3. 在其他组件中使用store对象中保存的状态即可
- 通过this.$store.属性 的方式来访问状态
- 通过this.$store.commit('mutation中方法')来修改状态
注意:
我们通过提交mutation的方式,而非直接改变$store.state.count
因为vuex可以更明确追踪state的变化,所以不要直接改变$store.state.count的值,通过数据流层来改变state的值
const store = new Vuex.Store({
state: {
count: 1000,
},
mutations: {
increment(state){
state.count++
},
decrement(state){
state.count--
}
}
})
{{ $store.state.count }}
methods: {
addition(){
return this.$store.commit('increment')
},
subtraction(){
return this.$store.commit('decrement')
}
}
getters相当于组件的computed
mutation相当于组件的methods
Vuex 使用单一状态树,用一个对象就包含了全部的应用层次状态。至此它便作为一个唯一的数据源而存在。这也意味着,每个应用将仅仅包含一个store实例。
单状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
用来从store获取Vue组件数据,类似于computed。
state: {
count: 1000,
},
getters: {
countPower(state) {
return state.count * state.count
},
},
state: {
students: [
{id:110, name: 'sylvia', age: 18},
{id:111, name: 'xxx', age: 20},
{id:112, name: 'dhy', age: 24},
{id:113, name: 'tyy', age: 30}
]
},
getters: {
more20stuLength(state,getters) {
// return state.students.filter(s => s.age >= 20).length
return getters.more20stu.length
},
},
state: {
students: [
{id:110, name: 'sylvia', age: 18},
{id:111, name: 'xxx', age: 20},
{id:112, name: 'dhy', age: 24},
{id:113, name: 'tyy', age: 30}
]
},
getters: {
moreAgeStu(state){
return function (age) {
return state.students.filter(s => s.age >= age).length
}
}
},
//调用
{{ $store.getters.moreAgeStu(18) }}
注意: getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。
事件处理器用来驱动状态的变化,类似于methods,同步操作。
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。
当外界需要通过mutation的handler 来修改state的数据时,不能直接调用 mutation的handler,而是要通过 commit 方法 传入类型。
store.mutations.increment,这种方式是错误的,必须使用 store.commit(‘increment’,value) ,value可作为要传递进入store的数据
你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload)
methods: {
addCount(count){
return this.$store.commit('addCount',count)
},
addStudent(){
const stu = { id:114,name:'aaa',age:33};
return this.$store.commit('addStudent',stu)
}
}
mutations: {
addCount(state,count) {
console.log(count); //传入的count数值,例如5,10
state.count += count
},
addStudent(state,stu){
state.students.push(stu)
}
}
提交 mutation 的另一种方式是直接使用包含 type 属性的对象。
当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数,因此 handler 保持不变:
addCount(state,payload) {
console.log(payload); //payload对象 {type: "addCount", count: 5}
state.count += payload.count
},
addCount(count){
return this.$store.commit({
type: 'addCount',
count
})
},
既然 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。
//mutation-types.js
export const INCREMENT = 'increment'
或者直接导出对象:
export default {
INCREMENT: 'increment'
}
import Vue from 'vue'
import Vuex from 'vuex'
import {INCREMENT} from "./mutation-types";
//1.安装插件
Vue.use(Vuex)
//2.创建对象
const store = new Vuex.Store({
state: {},
getters: {},
mutations: {
// 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
[INCREMENT](state){
state.count++
},
}
addition(){
return this.$store.commit(INCREMENT)
},
updateInfo(state) {
setTimeout(() => {
state.info.name = 'xxx'
},1000)
}
可以给组件使用的函数,以此用来驱动事件处理器 mutations,异步操作。
Action 类似于 mutation,不同在于:
actions: {
aUpdateInfo(context) {
setTimeout(() => {
context.commit('updateInfo')
})
}
}
updateInfo() {
// return this.$store.commit('updateInfo')
this.$store.dispatch('aUpdateInfo')
}
// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
})
// 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})
store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise:
actions: {
// aUpdateInfo(context,payload) {
// setTimeout(() => {
// context.commit('updateInfo')
// console.log(payload.message);
// payload.success()
// },1000)
// }
aUpdateInfo(context,payload) {
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('updateInfo')
console.log(payload)
resolve()
},1000)
})
}
}
updateInfo() {
// return this.$store.commit('updateInfo')
// this.$store.dispatch('aUpdateInfo',{
// message: '我是携带的信息',
// success: () => {
// console.log('里面已经完成了');
// }
// })
this.$store
.dispatch('aUpdateInfo','我是携带的信息')
.then(() => {
console.log('里面已经完成了');
})
}
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
假设模块A state 中 有 ‘city’,在外界访问时,则用 store.state.a.city
const moduleA = {
state: {
name: 'zhangsan'
},
getters: {
fullName(state) {
// 这里的 `state` 对象是模块的局部状态
return state.name + 'fullName'
},
fullName2(state,getters){
return getters.fullName + 'fullName2'
},
fullName3(state,getters,rootState) {
return getters.fullName2 + rootState.count
}
},
mutations: {
updateName(state,payload) {
state.name = payload
}
},
actions: {
aUpdateName(context){
console.log(context);
setTimeout(() =>{
context.commit('updateName','wangwu')
},1000)
}
},
}
const obj = {
name: 'xxx',
age: 22,
height: 1.60
}
const {name,age,height} = obj
console.log(name); //xxx
import getters from "./getters";
import mutations from "./mutations";
import actions from "./actions";
import moduleA from "./modules/moduleA";
const store = new Vuex.Store({
state,
getters,
mutations,
actions,
modules: {
a: moduleA
}
})
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
npm install axios --save
axios.get('/user', { //参数可拼接在URL后面
params: {
name: 'krislin'
}
}).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error)
}
axios.post('/user',{
name:'krislin',
address:'china'
})
.then(function(response){
console.log(response);
})
.catch(function(error){
console.log(error);
});
axios.all([
axios({
url: 'http://152.136.185.210:8000/api/n3/home/multidata'
}),
axios({
url: 'http://152.136.185.210:8000/api/n3/home/data',
params: {
type: 'sell',
page: 3
}
})
]).then(results => {
console.log(results);
})
//使用axios.spread()使两个结果分开
axios.all([ axios(),axios() ])
.then(axios.spread((res1,res2) => {
console.log(res1);
console.log(res2);
}))
可以通过向 axios 传递相关配置来创建请求:
// 发送 POST 请求
axios({
method: 'post',
url: '/user/12345',
//post使用data,get使用params
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
请求配置中,只有url是必须的,如果没有指明的话,默认是Get请求
const instance = axios.create({
baseURL: 'http://152.136.185.210:8000/api/n3',
timeout: 5000
})
instance({
url: '/home/data',
params: {
type: 'sell',
page: 1
}
}).then(res => {
console.log(res);
})
//添加一个请求拦截器
axios.interceptors.request.use(function(config){
//在请求发送之前做一些事
return config;
},function(error){
//当出现请求错误是做一些事
return Promise.reject(error);
});
//添加一个返回拦截器
axios.interceptors.response.use(function(response){
//对返回的数据进行一些处理
return response;
},function(error){
//对返回的错误进行一些处理
return Promise.reject(error);
});
var myInterceptor = axios.interceptors.request.use(function(){/*...*/});
axios.interceptors.rquest.eject(myInterceptor);
import axios from 'axios'
export function request(config) {
//1.创建axios的实例
const instance1 = axios.create({
baseURL: 'http://152.136.185.210:8000/api/n3',
timeout: 5000
})
//2.axios的拦截器
//2.1 请求拦截的作用
instance1.interceptors.request.use(config => {
//在发送请求之前做些什么
// console.log(config);
//1. 比如config中的一些信息不符合服务器的要求
//2. 比如每次发送网络请求时,都希望在界面显示一个请求的图标
//3. 某些网络请求(比如登录(token)),必须携带一些特殊的信息
return config
},err => {
// console.log(err);
})
//2.2 响应拦截
instance1.interceptors.response.use(res => {
//对响应数据做些什么
console.log(res);
return res.data
},err => {
console.log(err);
})
//3.4 发送真正的网络请求
return instance1(config)
}
import {request} from "./network/request";
request({
url: '/home/multidata'
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})