Github来源: | 求星星 ✨ | 给个❤️关注,❤️点赞,❤️鼓励一下作者
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。简单来说就是前端最火最简单的一个http请求解决方案。
工具类封装
// 引入axios
import axios from 'axios';
// 创建axios实例
const httpService = axios.create({
// url前缀-'https://some-domain.com/api/'
baseURL: process.env.BASE_API, // 需自定义
// 请求超时时间
timeout: 3000 // 需自定义
});
// request拦截器
httpService.interceptors.request.use(
config => {
// 根据条件加入token-安全携带
if (true) { // 需自定义
// 让每个请求携带token
config.headers['User-Token'] = '';
}
return config;
},
error => {
// 请求错误处理
Promise.reject(error);
}
)
// respone拦截器
httpService.interceptors.response.use(
response => {
// 统一处理状态
const res = response.data;
if (res.statuscode != 1) { // 需自定义
// 返回异常
return Promise.reject({
status: res.statuscode,
message: res.message
});
} else {
return response.data;
}
},
// 处理处理
error => {
if (error && error.response) {
switch (error.response.status) {
case 400:
error.message = '错误请求';
break;
case 401:
error.message = '未授权,请重新登录';
break;
case 403:
error.message = '拒绝访问';
break;
case 404:
error.message = '请求错误,未找到该资源';
break;
case 405:
error.message = '请求方法未允许';
break;
case 408:
error.message = '请求超时';
break;
case 500:
error.message = '服务器端出错';
break;
case 501:
error.message = '网络未实现';
break;
case 502:
error.message = '网络错误';
break;
case 503:
error.message = '服务不可用';
break;
case 504:
error.message = '网络超时';
break;
case 505:
error.message = 'http版本不支持该请求';
break;
default:
error.message = `未知错误${error.response.status}`;
}
} else {
error.message = "连接到服务器失败";
}
return Promise.reject(error);
}
)
/*网络请求部分*/
/*
* get请求
* url:请求地址
* params:参数
* */
export function get(url, params = {}) {
return new Promise((resolve, reject) => {
httpService({
url: url,
method: 'get',
params: params
}).then(response => {
resolve(response);
}).catch(error => {
reject(error);
});
});
}
/*
* post请求
* url:请求地址
* params:参数
* */
export function post(url, params = {}) {
return new Promise((resolve, reject) => {
httpService({
url: url,
method: 'post',
data: params
}).then(response => {
resolve(response);
}).catch(error => {
reject(error);
});
});
}
/*
* 文件上传
* url:请求地址
* params:参数
* */
export function fileUpload(url, params = {}) {
return new Promise((resolve, reject) => {
httpService({
url: url,
method: 'post',
data: params,
headers: { 'Content-Type': 'multipart/form-data' }
}).then(response => {
resolve(response);
}).catch(error => {
reject(error);
});
});
}
export default {
get,
post,
fileUpload
}
使用
// 引入工具类-目录自定义
import fetch from '@/util/fetch'
// 使用
const TMPURL = ''; // url地址
const params = {}; // 参数
fetch.post(TMPURL + '/login/login', params);
vuex是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。chrome安装调试工具 devtools extension
示意图说明:
一个简单的demo案例:
{{ count }}
中大型单页应用,需要考虑如何更好地在组件外部管理状态,简单应用不建议使用
示意图说明:
总结说明:
Vue组件接收交互行为,调用dispatch方法触发action相关处理,若页面状态需要改变,则调用commit方法提交mutation修改state,通过getters获取到state新值,重新渲染Vue Components,界面随之更新
npm install vuex --save
(1)src/vuex/store.js中写入以下代码:
// 引入vue
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
// 使用vuex
Vue.use(Vuex)
// 1、state:创建初始化状态
const state = {
// 放置初始状态
count: 1
}
// 2、mutations:创建改变状态的方法
const mutations = {
// 状态变更函数-一般大写
ADD (state, n) {
state.count += n;
}
}
// 3、getters:提供外部获取state
const getters = {
count: function(state){
return state.count;
}
}
// 4、actions:创建驱动方法改变mutations
const actions ={
// 触发mutations中相应的方法-一般小写
add ({commit}, data) {
commit('ADD', data)
}
}
// 5、全部注入Store中
const store = new Vuex.Store({
state,
mutations,
getters,
actions
});
// 6、输出store
export default store;
代码说明:
(2)src/main.js代码中
import Vue from 'vue'
import App from './App'
import router from './router'
// 引入store
import store from './vuex/store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store, // 全局注入
components: { App },
template: ' '
})
(3)src/compontent/Count.vue页面组件中代码如下:
{{ msg }}
{{count}}
{{ $store.state.count }}
// 方式1:直接获取
computed: {
count() {
// this指的是main.js中的vue实例对象
return this.$store.state.count;
}
}
// 方式2:利用mapState
computed: mapState({
// es5写法
count: function (state) {
return state.count;
},
// es6写法
count: state => state.count
})
// 方式3:数组获取
computed: mapState(['count'])
// 方式4:JSON获取
computed: mapState({
count: 'count'
})
(1)template中直接使用$store.commit( )触发
// template
// src/vuex/store.js
const mutations = {
// 状态变更函数
ADD (state) {
state.count++;
}
}
(2)利用mapMutations引入触发
{{ msg }}
{{count}}
(1)基本用法
// src/vuex/store.js
const getters = {
count: function(state){
// 返回加上100
return state.count + 100;
}
}
(2)常规获取值
computed: {
// 获取getters
count(){
return this.$store.getters.count;
}
}
(3)mapGetters获取值
// 1、引入mapMutations
import {mapState, mapMutations, mapGetters} from 'vuex'
// 2、使用
computed: {
// 获取getters
...mapGetters(["count"])
}
actions和mutations功能基本一样,不同点是,actions是异步的改变state状态,而mutations是同步改变状态。不过实际项目中一般都是通过actions改变mutations中的值。
(1)store.js中增加异步代码
// src/vuex/store.js
const actions ={
// 触发mutations中相应的方法
add ({commit}) {
// 增加异步
setTimeout(()=>{
commit('ADD')
},3000);
console.log('我比reduce提前执行');
}
}
(2)常规使用
// template
// script
methods: {
add() {
//分发action
this.$store.dispatch('add');
}
}
(3)mapActions的使用
// template
// script
// 引入mapActions
import {mapState, mapActions} from 'vuex'
// 使用mapActions
methods: {
...mapActions(['add'])
}
只需要在mutations和actions相应的地方加上参数,然后调用的时候传入即可。
(1)src/vuex/store.js中
// actions中传递参数
const mutations = {
ADD (state, n) {
state.count += n;
}
}
// actions中传递参数
const actions ={
// 触发mutations中相应的方法
add ({commit}, n) {
// 增加异步
setTimeout(()=>{
commit('ADD', n);
},3000);
console.log('我比reduce提前执行');
}
}
(2)页面组件常规调用传递
// template
// script
methods: {
add() {
// 分发action
this.$store.dispatch('add', 99);
}
}
(3)页面组件使用mapActions调用传递
// template
// script
methods: {
...mapActions(['add'])
}
当应用非常复杂,状态非常多的时候,需要将store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块,从上至下进行同样方式的分割。
// 模块A
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
// 模块B
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
// 组装
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
// 取值
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
实际开发中建议把module分开编写。
(1)src/vuex/module1.js
// 模块1
const module1 = {
// 初始化状态
state: {
module1: {
name: '模块1'
}
},
// 编写动作
mutations: {
CHANGE1 (state, data) {
state.module1 = data;
}
},
// 取值
getters: {
module1: function(state){
return state.module1;
}
},
// 创建驱动,可异步
actions: {
change1 ({commit}, data) {
commit('CHANGE1', data)
}
}
}
export default module1;
(2)src/vuex/module2.js
// 模块1
const module2 = {
// 初始化状态
state: {
module2: {
name: '模块2'
}
},
// 编写动作
mutations: {
CHANGE2 (state, data) {
state.module2 = data;
}
},
// 取值
getters: {
module2: function(state){
return state.module2;
}
},
// 创建驱动,可异步
actions: {
change2 ({commit}, data) {
commit('CHANGE2', data)
}
}
}
export default module2;
(3)src/vuex/store.js
// 引入vue
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
// 引入module1
import module1 from '@/vuex/module1'
// 引入module2
import module2 from '@/vuex/module2'
// 使用vuex
Vue.use(Vuex)
// 模块注入
const store = new Vuex.Store({
modules: {
a: module1,
b: module2
}
})
// 输出store
export default store;
(4)组件中使用,src/compontent/one.vue
{{ module1.name }}
{{ module2.name }}
PS:module中命名要唯一,不然获取值和改变值的时候会冲突,目前亲测mapGetters只能获取对象。
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。
包含的功能有:
使用命令安装:
npm install vue-router --save
在src/router/index.js文件中
// 引入vue框架
import Vue from 'vue'
// 引入vue-router路由依赖
import Router from 'vue-router'
// 引入页面组件,命名为HelloWorld
import HelloWorld from '@/components/HelloWorld'
// Vue全局使用Router
Vue.use(Router)
// 定义路由配置
export default new Router({
routes: [ //配置路由,这里是个数组
{ //每一个链接都是一个对象
path: '/', //链接路径
name: 'HelloWorld', //路由名称,
component: HelloWorld //对应的组件模板
}
]
})
在系统入口文件main.js中注入router,代码如下:
// 引入vue框架
import Vue from 'vue'
// 引入根组件
import App from './App'
// 引入路由配置
import router from './router'
// 关闭生产模式下给出的提示
Vue.config.productionTip = false
// 定义实例
new Vue({
el: '#app',
router, // 注入框架中
components: { App },
template: ' '
})
在html标签内使用router-link跳转,相应于超链接a标签,使用方式如下:
[显示字段]
to:导航路径
使用示例如下:
导航 :
首页
hello
实际项目中,很多时候都是通过在JS代码内部进行导航的跳转,使用方式如下:
this.$router.push('/xxx')
具体的简单用法:
(1)先编写一个按钮,在按钮上绑定goHome( )方法。
(2)在模块里加入goHome方法,并用
this.$router.push
(‘/’)导航到首页
export default {
name: 'app',
methods: {
goHome(){
this.$router.push('/home');
}
}
}
// 后退一步记录,等同于 history.back()
this.$router.go(-1)
// 在浏览器记录中前进一步,等同于 history.forward()
this.$router.go(1)
子路由,也叫路由嵌套,采用在children后跟路由数组来实现,数组里和其他配置路由基本相同,需要配置path和component,然后在相应部分添加来展现子页面信息,相当于嵌入iframe。具体看下面的示例:
{{ msg }}
导航 :
首页 |
-子页面1 |
-子页面2
{{ msg }}
{{ msg }}
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import One from '@/components/One'
import Two from '@/components/Two'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', // 默认页面重定向到主页
redirect: '/home'
},
{
path: '/home', // 主页路由
name: 'Home',
component: Home,
children:[ // 嵌套子路由
{
path:'one', // 子页面1
component:One
},
{
path:'two', // 子页面2
component:Two
},
]
}
]
})
标签中的to传参基本语法:
valueString
PS:上面to前边是带冒号,后边跟的是一个对象形势的字符串
具体实例如下:
(1)在src/components/Home.vue里面导航中添加如下代码:
子页面1
(2)在src/router/indes.js中添加如下代码,重点是name:
{
path:'one', // 子页面1
name: 'one', // 路由名称-命名路由
component:One
}
(3)在src/components/One.vue里面接受参数,代码如下:
{{$route.params.username}}
(1)在路由中以冒号传递,在src/router/index.js中加入如下代码:
{
path:'/home/two/:id/:name', // 子页面2
component:Two
},
(2)接受参数,在src/components/Two.vuez中加入如下代码:
ID:{{ $route.params.id}}
名称:{{ $route.params.name}}
(3)路由跳转,在src/components/Home.vue中加入如下代码:
子页面2
PS:to前没有冒号为字符串路由,必须全部匹配。
(4)如果路由参数需要有特定的规则,就需要加入正则表达式了,示例如下:
{
path:'/home/two/:id(\d+)/:name', // 子页面2
component:Two
}
(1)在src/router/index.js页面加入如下代码:
{
path:'/home/three', // 子页面3
name: 'three',
component:Three
}
(2)在src/components/Three.vue页面加入如下代码:
ID:{{ $route.params.id}}
名称:{{ $route.params.name}}
(3)在src/components/Home.vue中加入如下代码:
// template
// script
methods: {
toThreePage() {
this.$router.push({name: 'three', params: {id: 1, name: 'zhangsan'}})
}
}
说明:
A、动态路由使用params传递参数,在this.$router.push() 方法中path不能和params一起使用,否则params将无效。需要用name来指定页面。
B、以上方式参数不会显示到浏览器的地址栏中,如果刷新一次页面,就获取不到参数了,改进方式将第一部中的代码改成如下:
{
path:'/home/three/:id/:name', // 子页面3
name: 'three',
component:Three
}
(1)在src/router/index.js页面加入如下代码:
{
path:'/home/three', // 子页面3
name: 'three',
component:Three
}
(2)在src/components/Three.vue页面加入如下代码:
ID:{{ $route.query.id}}
名称:{{ $route.query.name}}
(3)在src/components/Home.vue中加入如下代码:
// template
// script
methods: {
toThreePage() {
this.$router.push({path: '/home/three', query: {id: 1, name: 'zhangsan'}})
}
}
PS:动态路由使用query传递参数,会显示到浏览器地址栏中,以上链接为
/home/three?id=1&name=zhangsan
给一个路由命一个唯一的名称,然后跳转调用这个名称即可。
(1)在src/router/index.js中加一个带name的路由,代码如下:
{
path: 'one', // 子页面1
name: 'one', // 路由名称-命名路由
component: One // 页面组件
}
(2)在src/component/Home.vue页面中调用,代码如下:
// template跳转调用
子页面1
// router.push函数跳转调用
router.push({ name: 'user'}})
在同一个页面展示多个视图,如果不用嵌套,只能采用命名视图来实现了,代码如下:
(1)在src/router/index.js中,代码如下:
import Vue from 'vue'
import Router from 'vue-router'
// 创建页面组件
const Header = { template: 'Header' }
const Left = { template: 'Left' }
const Right = { template: 'Right' }
Vue.use(Router)
export default new Router({
routes: [
{
path: '/', // 主页路由
components: {
default: Header,
a: Left,
b: Right
}
}
]
})
(2)在src/App.vue中,代码如下:
PS:经过实践,命名视图只能放在最顶级的页面中,即第一步中的代码不能放在其他页面中。
重定向是通过route的配置中关键词redirect来实现的,具体代码如下:
(1)在src/router/index.js中,代码如下:
export default new Router({
routes: [
{
path: '/', // 默认页面重定向到主页
redirect: '/home' // 重定向
},
{
path: '/home', // 主页路由
component: Home,
children:[ // 嵌套子路由
{
path:'/home/two/:id/:name', // 子页面2
component:Two
},
{
path:'/home/three/:id/:name', // 子页面3
name: 'three', // 路由名称-命名路由
redirect: '/home/two/:id/:name' // 重定向-传递参数
},
]
}
]
})
(2)在src/components/Home.vue中,代码如下:
首页 |
子页面2 |
子页面3
说明1-不带参数的重定向:
redirect: '/home' // 重定向-不带参数
说明2-带参数的重定向:
redirect: '/home/two/:id/:name' // 重定向-传递参数
重定向是通过route的配置中关键词alias来实现的,具体代码如下:
(1)在src/router/index.js中,代码如下:
{
path:'/one', // 子页面1
component:One,
alias: '/oneother'
}
(2)在src/components/Home.vue中,代码如下:
子页面1
说明1:redirect和alias的区别
中的内容。说明2:
别名请不要用在path为’/’中,如下代码的别名是不起作用的。
{
path: '/',
component: Hello,
alias:'/home'
}
(1)在
标签的外部添加
标签,标签还需要一个name属性,代码如下:
(2)加入CSS,一共4个CSS类名,四个类名与transition的name属性有关,比如name=”fade”,相应的css如下:
/*页面切换动画*/
/*进入过渡的结束状态,元素被插入时就生效,在过渡过程完成后移除*/
.fade-enter-active {
transition: opacity .5s;
}
/*进入过渡的开始状态,元素被插入时生效,只应用一帧后立刻删除*/
.fade-enter {
opacity: 0;
}
/*离开过渡的开始状态,元素被删除时触发,只应用一帧后立刻删除*/
.fade-leave {
opacity: 1;
}
/*离开过渡的结束状态,元素被删除时生效,离开过渡完成后被删除*/
.fade-leave-active {
opacity:0;
transition: opacity .5s;
}
代码示例:
export default new Router({
mode: 'history', //mode模式
routes: [...]
})
mode取值说明:
(1)histroy:URL就像正常的 url,示例:http://localhost:8080/home
(2)hash:默认值,会多一个“#”,示例:http://localhost:8080/#/home
如果访问的路由不存在,或者用户输入错误时,会有一个404友好的提示页面,配置如下:
(1)在/src/router/index.js中加入如下代码:
// 404
{
path: '*',
component: () => import('@/components/404')
}
(2)在src/components/404.vue中编写如下代码:
404 not found
路由钩子,即导航钩子,其实就是路由拦截器,vue-router一共有三类:
在src/router/index.js中使用,代码如下:
// 定义路由配置
const router = new VueRouter({ ... })
// 全局路由拦截-进入页面前执行
router.beforeEach((to, from, next) => {
// 这里可以加入全局登陆判断
// 继续执行
next();
});
// 全局后置钩子-常用于结束动画等
router.afterEach(() => {
//不接受next
});
export default router;
每个钩子方法接收三个参数:
to: Route : 即将要进入的目标 [路由对象]
from: Route : 当前导航正要离开的路由
next: Function : 继续执行函数
使用:在路由配置中单独加入钩子,在src/router/index.js中使用,代码如下:
{
path:'/home/one', // 子页面1
component: One,
// 路由内钩子
beforeEnter: (to, from, next) => {
console.log('进入前执行');
next();
}
}
使用:在路由组件内定义钩子函数:
任意找一页面,编写如下代码:
// 1、先引入页面组件
import Home from '@/components/Home'
// 2、使用组件
{
path: '/home',
component: Home
}
大项目中,为了提高初始化页面的效率,路由一般使用懒加载模式,一共三种实现方式。
(1)第一种写法:
component: (resolve) => require(['@/components/One'], resolve)
(2)第二种写法:
component: () => import('@/components/Two')
(3)第三种写法:
components: r => require.ensure([], () => r(require('@/components/Three')), 'group-home')
PS:
vue-cli是vue官方出品的快速构建单页应用的脚手架,里面集成了webpack,npm,nodejs,babel,vue,vue-router等.
全局安装vue-cli,命令行:
npm install vue-cli -g
在实际开发中,一般都会使用webpack这个模板,命令使用如下:
vue init webpack my-vue-demo
npm run dev
以上命令为开发模式下运行项目
npm run build
以上命令为项目发布打包
// 引入vue框架
import Vue from 'vue'
// 引入根组件
import App from './App'
// 引入路由配置
import router from './router'
// 关闭生产模式下给出的提示
Vue.config.productionTip = false
// 定义实例
new Vue({
el: '#app',
router,
components: { App },
template: ' '
})
// 引入vue框架
import Vue from 'vue'
// 引入vue-router路由依赖
import Router from 'vue-router'
// 引入页面组件,命名为HelloWorld
import HelloWorld from '@/components/HelloWorld'
// 使用路由依赖
Vue.use(Router)
// 定义路由配置
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
Vue入门之组件
我是template标签模板
(1)全局注册
// script
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: ''
});
new Vue({
el: '#app'
});
// html使用
(2)局部注册
// script
new Vue({
el: '#app',
components:{
"button-inner":{
data: function() {
return {
inner: 0
}
},
template: ''
}
}
});
// html使用
vue中的自定义指令通过Vue.directive来实现
Vue入门之自定义指令
{{num}}
$on接收两个参数,第一个参数是调用时的事件名称,第二个参数是一个匿名方法
app.$on('reduce',function(){
console.log('执行了reduce()');
this.count--;
});
app.$once('reduceOnce',function(){
console.log('只执行一次的方法');
this.count--;
});
function off(){
console.log('关闭事件');
app.$off('reduce');
}
扩展:对构造器进行扩展
// 扩展
var extendObj ={
created: function(){
console.log("我是被扩展出来的");
}
}
// 实例化vue
var app = new Vue({
// 挂载实例
el:'#app',
// 页面数据初始化,字符,对象、数组
data:{
},
// 扩展
extends: extendObj
})
我是Jeskson
(达达前端),感谢各位人才的:点赞、收藏和评论,我们下期见!(如本文内容有地方讲解有误,欢迎指出☞谢谢,一起学习了)
github
收录,欢迎Star
:https://github.com/webVueBlog/WebFamily