什么是Vue CLI:
Vue CLI使用前提:
Vue CLI的使用:
Vue CLI2详解:


(运行时+编译器)Runtime-Compiler和(只含有运行时版本)Runtime-only的区别:
如果你需要在客户端编译模板(例如, 向template 选项传入一个字符串,或者需要将模 板中的非DOM的HTML挂载到一个元素),你需要带有编译器的版本,因而需要完整构建版本。
在使用vue-loader或vueify 时,* . vue文件中的模板会在构建时(build time)预编译(pre-compile)为JavaScript.最终生成的bundle中你不再需要编译器(compiler),因此可以直接使用只含有运行时的构建版本(runtime- only)。
//这种情况需要编译器(compiler)
new Vue({
template: ‘
//这种情况不需要
new Vue({
render (h) {
return h(‘div’, this.h1)
}
})
由于只含有运行时构建版本(runtime-only)比完整构建版本(ull-build)轻量大约30%,你应该尽可能使用只含有运行时的构建版本。如果你还是希望使用完整构建版本,则需要在打包器中配置别名。
简单总结:
①如果在之后的开发中,你依然使用template,就需要选择Runtime-Compiler。
②如果你之后的开发中,使用的是.vue文件夹开发,那么可以选择Runtime-only。
render和template区别:
//Runtime-Compiler
new Vue({
el :'#app',
components: { App },
template: ' '
})
//Runtime-only
new Vue({
el : '#app',
render: h => h(App)
})

npm run build与npm run dev详解:


webpack.base.conf.js起别名:
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@':resolve('src'),
'pages': resolve('src/pages'),
'common': resolve('src/common'),
'components':resolve('src/components'),
'network': resolve('src/network')
}
},
Vue CLI3详解:




什么是路由?
后端路由阶段:
前端路由阶段:
URL的hash:
URL的hash也就是锚点(#), 本质上是改变window.location的href属性.
我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新
执行:location.hash = ‘/foo’
返回:“/foo”
执行:location. href
返回:“http: //192.168.1.101: 8000/examples/urlChange/#/foo”
HTML5的history模式:
与URL的hash相比,没有了#符号。vue-router认识:
安装和使用vue-router:
安装vue-router:npm install vue-router --save
在模块化工程中使用它(因为是一个插件, 所以可以通过Vue.use()来安装路由功能)
①导入路由对象,并且调用 Vue.use(VueRouter)
②创建路由实例,并且传入路由映射配置
③在Vue实例中挂载创建的路由实例
使用vue-router的步骤:
①创建路由组件
②配置路由映射: 组件和路径映射关系
③使用路由: 通过和
路由标签详解:
①: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个标签.
②: 该标签会根据当前的路径, 动态渲染出不同的组件。
③网页的其他内容, 比如顶部的标题/导航,或者底部的一些版权信息等会和处于同一个等级。
④在路由切换时, 切换的是挂载的组件,其他内容不会发生改变。
----创建router文件夹,然后创建index.js文件,创建router实例,配置组件和路径的映射关系:----
import Vue from ‘vue’
import VueRouter from ‘vue-router’
// 1.注入插件
Vue.use(VueRouter)
// 2.定义路由
const routes = [
{
path: ‘/home’,
component: Home
}
{
path: ‘/about’,
component: About
}
]
// 3.创建router实例
const router = new VueRouter({
routes
})
// 4.导出router实例
export default router
----main.js文件中挂载到Vue实例中:----
import Vue from ‘vue’
import App from ‘./App’
import router from ‘./router’
new Vue({
el: ‘#app’,
router,
render: h => h(App)
})
----创建About和Home路由组件----
----使用路由:----
----最终效果如下:----
一、当路径是根路径时,router-view没有渲染试图
二、点击首页,路径切换,router-view渲染home组件
伞、点击关于,路径切换,router-view渲染about组件
vue-router细节处理:
路由的默认路径:
①默认情况下, 进入网站的首页, 我们希望渲染首页的内容,但是我们的实现中, 默认没有显示首页组件, 必须让用户点击才可以。
②如何可以让路径默认跳到到首页, 并且渲染首页组件呢,非常简单, 我们只需要配置多配置一个映射就可以了。
③我们在routes中又配置了一个映射,path配置的是根路径: /,redirect是重定向, 也就是我们将根路径重定向到/home的路径下, 这样就可以得到我们想要的结果了。
const routes =[
{
path: ‘/’
redirect: ‘/home’
}
]
HTML5的History模式:
①我们前面说过改变路径的方式有两种:URL的hash,HTML5的history。默认情况下, 路径的改变使用的URL的hash,如果希望使用HTML5的history模式, 非常简单, 进行如下配置即可:
const router = new VueRouter({
routes,
mode: ‘history’
})
router-link补充:
①在前面的中, 我们只是使用了一个属性: to, 用于指定跳转的路径。
②还有一些其他属性:
<1>tag: tag可以指定之后渲染成什么组件, 比如上面的代码会被渲染成一个
replace: replace不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中。active-class: 当对应的路由匹配成功时, 会自动给当前元素设置一个router-link-active的class, 设置active-class可以修改默认的名称。在进行高亮显示的导航菜单或者底部tabbar时, 会使用到该类。但是通常不会修改类的属性, 会直接使用默认的router-link-active即可。
修改linkActiveClass:
①该class具体的名称也可以通过router实例的属性进行修改。
const router = new VueRouter({
routes,
mode: ‘history’,
linkActiveClass:‘active’
})
路由代码跳转:
①有时候, 页面的跳转可能需要执行对应的JavaScript代码, 这个时候, 就可以使用第二种跳转方式了。
路由懒加载:
官方给出了解释:当打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了
官方在说什么呢首先, 我们知道路由中通常会定义很多不同的页面.这个页面最后被打包在哪里呢 一般情况下, 是放在一个js文件中.但是, 页面这么多放在一个js文件中, 必然会造成这个页面非常的大.如果我们一次性从服务器请求下来这个页面, 可能需要花费一定的时间, 甚至用户的电脑上还出现了短暂空白的情况.
如何避免这种情况呢 使用路由懒加载就可以了.路由懒加载做了什么路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块.只有在这个路由被访问到的时候, 才加载对应的组件。
懒加载的方式:
方式一: 结合Vue的异步组件和Webpack的代码分析.
const Home = resolve => { require.ensure([‘…/components/Home.vue’], () => { resolve(require(‘…/components/Home.vue’)) })};
方式二: AMD写法
const About = resolve => require([‘…/components/About.vue’], resolve);
方式三: 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.
const Home = () => import(‘…/components/Home.vue’)
//使用懒加载
const routes =[
{
path: ‘/home’, component: () => import(’ …/components/Home’)
},
path: ‘/about’, component: () => import(‘…/components/About’)
},
];
路由嵌套:
嵌套路由是一个很常见的功能。比如在home页面中, 我们希望通过/home/news和/home/message访问一些内容。一个路径映射一个组件, 访问这两个路径也会分别渲染两个组件。路径和组件的关系如下:
/home --------> Home
/home/news --------> News
/home/message --------> Message
/about --------> About
实现嵌套路由有两个步骤:
①创建对应的子组件, 并且在路由映射中配置对应的子路由。
②在组件内部使用标签。
-----一、定义两个组件-----
-----二、配置嵌套路由映射-----
import Vue from ‘vue’
import VueRouter from ‘vue-router’
const Home = () => import(‘…/components /Home’)
const Message = () => import(‘…/components/message’)
const News = () => import(‘…/components/news’)
const About = ( ) => import(‘…/components/About’)
// 1.注入插件
Vue.use (VueRouter)
// 2.定义路由
const routes = [
{
path: ‘/home’,
component: Home,
children: [
{
path: ‘message’
component: Message
},
{
path: ‘news’,
component: News
}
]
}
]
-----三、在父组件模板中使用-----
嵌套路由也可以配置默认的路径, 配置方式如下:
{
path: ‘’,
redirect:‘message’
}
路由传递参数:
传递参数主要有两种类型: params和query
params的类型:
①配置路由格式: /router/:id
②传递的方式: 在path后面跟上对应的值
③传递后形成的路径: /router/123, /router/abc
query的类型:
①配置路由格式: /router, 也就是普通配置
②传递的方式: 对象中使用query的key作为传递方式
③传递后形成的路径: /routerid=123, /routerid=abc
如何使用它们呢 也有两种方式: 的方式和JavaScript代码方式
----传递参数方式一: :----
path: ‘/profile/’ + 123,
query: { name:‘why’,age: 18}
}”
档案
----传递参数方式二: JavaScript代码:----
export default {
name:‘App’,
methods: {
toProfile() {
this.$router.push({
path: ‘/profile/’ + 123,
query: {name: ‘why’,age: 18}
})
}
}
}
获取参数:
①获取参数通过
r
o
u
t
e
对象获取的,在使用了
v
u
e
−
r
o
u
t
e
r
的应用中,路由对象会被注入每个组件中,赋值为
t
h
i
s
.
route对象获取的,在使用了vue-router 的应用中,路由对象会被注入每个组件中,赋值为 this.
route对象获取的,在使用了vue−router的应用中,路由对象会被注入每个组件中,赋值为this.route,并且当路由切换时,路由对象会被更新。
②通过$route获取传递的信息如下:
params: {{ $route.params}}
query: {{$route.query}}
r
o
u
t
e
和
route和
route和router是有区别的:
①
r
o
u
t
e
r
为
V
u
e
R
o
u
t
e
r
实例,想要导航到不同
U
R
L
,则使用
router为VueRouter实例,想要导航到不同URL,则使用
router为VueRouter实例,想要导航到不同URL,则使用router.push方法
②$route为当前router跳转对象里面可以获取name、path、query、params等
路由导航守卫:
我们来考虑一个需求: 在一个SPA应用中, 如何改变网页的标题呢
①网页标题是通过
普通的修改方式:
①我们比较容易想到的修改标题的位置是每一个路由对应的组件.vue文件中.
②通过mounted声明周期函数, 执行对应的代码进行修改即可.
③但是当页面比较多时, 这种方式不容易维护(因为需要在多个页面执行类似的代码).
有没有更好的办法呢 使用导航守卫即可,什么是导航守卫
①vue-router提供的导航守卫主要用来监听监听路由的进入和离开的.
②vue-router提供了beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发.
详解:
①我们可以在钩子当中定义一些标题, 可以利用meta来定义。
②导航钩子的三个参数解析:
<1>to: 即将要进入的目标的路由对象.
<2>from: 当前导航即将要离开的路由对象.
<3>next: 调用该方法后, 才能进入下一个钩子
// 定义路由
const routes =[
{
path:"/home’,
component: Home,
children: […],
meta:{
title:‘首页’
}
},
{
path: ‘/about’,
component: About,
meta: {
title:‘关于’
}
},
{
path: ‘/profile/:id’,
component: Profile ,
meta: {
title:‘档案’
}
}
]
//配置路由
const router = new VueRouter ({
routes,
mode: ‘history’,
linkActiveClass: ‘active’,
})
router.beforeEach( (to, from, next) => {
window.document.title = to.meta.title
next()
})
补充:
①如果是后置钩子, 也就是afterEach, 不需要主动调用next()函数.
②上面我们使用的导航守卫, 被称之为全局守卫.
<1>路由独享的守卫.
<2>组件内的守卫.
路由keep-alive:
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。它们有两个非常重要的属性:
①include - 字符串或正则表达,只有匹配的组件会被缓存
②exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存:
什么是Promise呢?
Promise基本使用:
new Promise很明显是创建一个Promise对象。小括号中((resolve, reject) => {})也很明显就是一个函数,而且我们这里用的是之前刚刚学习过的箭头函数。但是resolve, reject它们是什么呢?
我们先知道一个事实:在创建Promise时,传入的这个箭头函数是固定的(一般我们都会这样写)
resolve和reject它们两个也是函数,通常情况下,我们会根据请求数据的成功和失败来决定调用哪一个。
成功还是失败?
①如果是成功的,那么通常我们会调用resolve(messsage),这个时候,我们后续的then会被回调。
②如果是失败的,那么通常我们会调用reject(error),这个时候,我们后续的catch会被回调。
//普通方式
setTimeout( function () {
let data = ‘Hello World’
console. log (content) ;
}, 1000)
//Promise方式
new Promise((resolve, reject) => {
setTimeout( function () {
resolve( ‘Hello World’)
reject( ‘Error Data’)
}, 1000)
}).then(data => {
console. log(data);
}).catch(error => {
console. log(error);
})
Promise三种状态:

Promise链式调用:
我们在看Promise的流程图时,发现无论是then还是catch都可以返回一个Promise对象。所以,我们的代码其实是可以进行链式调用的:
①这里我们直接通过Promise包装了一下新的数据,将Promise对象返回了
<1>Promise.resovle():将数据包装成Promise对象,并且在内部回调resolve()函数
<2>Promise.reject():将数据包装成Promise对象,并且在内部回调reject()函数
//链式调用的代码
new Promise((resolve, reject) => {
setTimeout(function () {
resolve(‘Hello World’)
},1000 )
}). then(data => {
console. log(data); // => Hello World
return Promise. resolve(data + ‘111’)
}). then(data => {
console. log(data); // => Hello World111
return Promise. resolve(data + ‘222’)
}). then(data => {
console. log(data); // => Hello World111222
return Promise.reject(data + ‘error’)
}). then(data => {
console. log(data); //这里没有输出,这部分代码不会执行
return Promise. resolve(data + ‘333’)
}).catch(data => {
console. log(data); // => Hello World111222error
return Promise. resolve(data + ‘444’)
}).then(data => {
console. log(data); // => Hello World111222error444
})
简化版代码:如果我们希望数据直接包装成Promise.resolve,那么在then中可以直接返回数据
注意下面的代码中,我将return Promise.resovle(data)改成了return data。结果依然是一样的。
//链式调用的简便写法
new Promise((resolve, reject) => {
setTimeout(function () {
resolve( ‘Hello World’)
},1000)
}). then(data => {
console. log(data); // => Hello World
return data + '111 ’
}). then(data => {
console. log(data); // => Hello World111
return data + ‘222’
}). then(data => {
console. log(data); // => Hello World111222
return Promise. reject(data + ‘error’)
}). then(data =>
console. log(data); //这里没有输出,这部分代码不会执行
return data + ’ 333
}).catch(data => {
console. log(data); // => Hello World111222error
return data + ’ 444
}). then(data => {
console. log(data); // => Hello World111222error444
})
如果希望返回的是reject方法,可以直接throw "字符串"。
Vuex是做什么的
Vuex详解:


Vuex基本使用:
首先,我们需要在某个地方存放我们的Vuex代码: 这里,我们先创建一个文件夹store,并且在其中创建一个index.js文件,在index.js文件中写入如下代码:
import Vuex from ‘vuex’
import Vue from ‘vue’
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
},
decrement(state) {
state.count–
}
}
})
export default store
其次,我们让所有的Vue组件都可以使用这个store对象 来到main.js文件,导入store对象,并且放在new Vue中这样,在其他Vue组件中,我们就可以通过this.$store的方式,获取到这个store对象了
import Vue from ‘vue’
import App from ‘./App’
import store from ‘./store’
new Vue({
el: ‘#app’,
store,
render: h => h(App)
})
使用Vuex的count:
{{count}}
Vuex核心概念:
State简介:
Getters简介:
有时候,我们需要从store中获取一些state变异后的状态,我们可以在Store中定义getters。
getters默认是不能传递参数的, 如果希望传递参数, 那么只能让getters本身返回另一个函数。
Getters类似计算属性。
getters: {
//直接获取store数据
greaterAgesStus: state => {
return state.students.filter(s => s.age >= 20)
},
//获取getters数据
greaterAgesCount: (state, getters) => {
return getters.greaterAgesstus.length
},
stuByID: state => {
return id => {
return state.students.find(s => s.id === id)
}
}
}
Mutation简介:
Vuex的store状态的更新唯一方式:提交Mutation
Mutation主要包括两部分:
①字符串的事件类型(type)
②一个回调函数(handler),该回调函数的第一个参数就是state。
//multation的定义方式:
mutations: {
increment(state) {
state.count++
}
}
//通过mutation更新:
increment: function () {
this.$store.commit(‘increment’)
}
在通过mutation更新数据的时候, 有可能我们希望携带一些额外的参数:参数被称为是mutation的载荷(Payload)。
------单参数:-------
//multation的定义方式:
decrement(state,n) {
state.count -= n
}
//通过mutation更新:
decrement: function () {
this.Sstore.commit(‘decrement’,2)
}
------对象:-------
//multation的定义方式:
changeCount (state,payload) {
state.count = payload.count
}
//通过mutation更新:
changeCount: function () {
this.$store.commit(‘changeCount’, {count: 0})
}
Mutation提交风格:
①上面的通过commit进行提交是一种普通的方式。
②Vue还提供了另外一种风格, 它是一个包含type属性的对象:
//通过mutation更新:
this.$store.commit ({
type:‘changeCount’
count: 100
})
//Mutation中的处理方式是将整个commit的对象作为payload使用, 所以代码没有改变, 依然如下:
changeCount (state,pay1oad) {
state.count = payload.count
}
Mutation响应规则:
①Vuex的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新.
②这就要求我们必须遵守一些Vuex对应的规则:
<1>提前在store中初始化好所需的属性.
<2>当给state中的对象添加新属性时, 使用下面的方式:
方式一: 使用Vue.set(obj, ‘newProp’, 123)
方式二: 用心对象给旧对象重新赋值
Mutation常量类型:
①在mutation中, 我们定义了很多事件类型(也就是其中的方法名称),当我们的项目增大时, Vuex管理的状态越来越多, 需要更新状态的情况越来越多, 那么意味着Mutation中的方法越来越多,方法过多, 使用者需要花费大量的经历去记住这些方法, 甚至是多个文件间来回切换, 查看方法名称, 甚至如果不是复制的时候, 可能还会出现写错的情况。
②在各种Flux实现中, 一种很常见的方案就是使用常量替代Mutation事件的类型,我们可以将这些常量放在一个单独的文件中, 方便管理以及让整个app所有的事件类型一目了然。
③我们可以创建一个文件: mutation-types.js, 并且在其中定义我们的常量,定义常量时, 我们可以使用ES2015中的风格, 使用一个常量来作为函数的名称。
文件名:mutation-typesjs
代码:export const UPDATE_ INFO = ‘UPDATE_INFO’
Mutation同步函数:
①通常情况下, Vuex要求我们Mutation中的方法必须是同步方法,主要的原因是当我们使用devtools时, 可以devtools可以帮助我们捕捉mutation的快照。
②但是如果是异步操作, 那么devtools将不能很好的追踪这个操作什么时候会被完成。所以通常情况下, 不要再mutation中进行异步的操作。
Action简介:
我们强调, 不要再Mutation中进行异步操作. 但是某些情况, 我们确实希望在Vuex中进行一些异步操作, 比如网络请求,必然是异步的. 这个时候怎么处理呢
Action类似于Mutation, 但是是用来代替Mutation进行异步操作的.
context是什么
①context是和store对象具有相同方法和属性的对象.
②也就是说, 我们可以通过context去进行commit相关的操作, 也可以获取context.state等.但是注意, 这里它们并不是同一个对象, 为什么呢? 我们后面学习Modules的时候, 再具体说。
这样的代码是否多此一举呢
①我们定义了actions, 然后又在actions中去进行commit, 这不是脱裤放屁吗
②事实上并不是这样, 如果在Vuex中有异步操作, 那么我们就可以在actions中完成了.
Action的分发:
①在Vue组件中, 如果我们调用action中的方法, 那么就需要使用dispatch。
②同样的, 也是支持传递payload
Action返回的Promise:
①在Action中, 我们可以将异步操作放在一个Promise中, 并且在成功或者失败后, 调用对应的resolve或reject。
\定义:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
increment (context) {
context.commit(‘increment’)
}
}
})
\使用:
methods: {
increment() {
this.$store.dispatch(‘increment’)
}
}
Module简介:
Module是模块的意思, 为什么在Vuex中我们要使用模块呢
①Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理,当应用变得非常复杂时,store对象就有可能变得相当臃肿。
②为了解决这个问题, Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutation、action、getters等。
注意:
①虽然, 我们的getters和mutation都是定义在对象内部的,但是在调用的时候, 依然是通过this.$store来直接调用的。
②actions:
<1>局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState
<2>如果getters中也需要使用全局的状态, 可以接受更多的参数
const moduleA = {
//…
actions: {
incrementIfoddonRootSum ({state,commit,rootState}) {
if ((state.count + rootState.count) %2 ===1) {
commit(‘increment’)
}
}
}
}
代码结构:
const moduleA = {
state: { … },
mutations: { … },
actions: { … },
getters: { … }
}
const moduleB = {
state: { … },
mutations: { … },
actions: { … }
}
const store = new Vuex.Store({
modules: {
a: modu1eA,
b: modu1eB
}
})
store.state.a // -> moduleA的状态
store.state.b // -> moduleB的状态
项目结构:

选择什么网络模块
jsonp:
为什么选择axios
axiox请求方式:
支持多种请求方式:
①axios(config)
②axios.request(config)
③axios.get(url[, config])
④axios.delete(url[, config])
⑤axios.head(url[, config])
⑥axios.post(url[, data[, config]])
⑦axios.put(url[, data[, config]])
⑧axios.patch(url[, data[, config]])
发送get请求演示:
import axios from ‘axios’
export default {
name : ‘app’,
created() {
//提问:为什么我这里没有跨域的问题?//
1.没有请求参数
axios.get( ‘http://123.207.32.32:8000/category’)
.then(res => {
console.log(res);
}).catch(err =>{
console.log(err);
})
//2.有请求参数
axios.get( 'http:/ /123.207.32.32:8000/home/data',
{params: itype: 'sell', page: 1}})
.then(res => {
console.log ( res);
}).catch(err => {
console.log(err);
})
}
}
发送并发请求:
①有时候, 我们可能需求同时发送两个请求
②使用axios.all, 可以放入多个请求的数组.
③axios.all([]) 返回的结果是一个数组,使用 axios.spread 可将数组 [res1,res2] 展开为 res1, res2
import axios from ‘axios’
export default {
name : ‘app’,
created () {[
//发送并发请求
axios.all([axios.get(‘http://123.207.32.32:8000/category’),
axios.get(‘http://123.207.32.32:8000/home/data’,
{params : {type: ‘sell’, page: 1}})])
.then(axios.spread((res1,res2) => {
console.log(res1);
console.log(res2);
}))
}
全局配置:
在上面的示例中, 我们的BaseURL是固定的
①事实上, 在开发中可能很多参数都是固定的.
②这个时候我们可以进行一些抽取, 也可以利用axiox的全局配置
created( {
//提取全局的配置
axios.defaults.baseURL = ‘http://123.207.32.32:8000’
//发送并发请求
axios.all([
axios.get('/category'),
axios.get('/home/data',
{params: {type: 'sell', page:1}})])
.then(axios.spread((res1,res2) =>{
console.log (res1);
console.log(res2);
}))
}
常见的配置选项:
请求地址
url: ‘/user’,
请求类型
method: ‘get’,
请根路径
baseURL: ‘http://www.mt.com/api’,
请求前的数据处理
transformRequest:[function(data){}],
请求后的数据处理
transformResponse: [function(data){}],
自定义的请求头
headers:{‘x-Requested-With’:‘XMLHttpRequest’},
URL查询对象
params:{ id: 12 },
查询对象序列化函数
paramsSerializer: function(params){ }
request body
data: { key: ‘aa’},
超时设置s
timeout: 1000,
跨域是否带Token
withCredentials: false,
自定义请求处理
adapter: function(resolve, reject, config){},
身份验证信息
auth: { uname: ‘’, pwd: ‘12’},
响应的数据格式 json / blob /document /arraybuffer / text / stream
responseType: ‘json’,
axios的实例:
为什么要创建axios的实例呢
①当我们从axios模块中导入对象时, 使用的实例是默认的实例.
②当给该实例设置一些默认配置时, 这些配置就被固定下来了.
③但是后续开发中, 某些配置可能会不太一样.
④比如某些请求需要使用特定的baseURL或者timeout或者content-Type等.
⑤这个时候, 我们就可以创建新的实例, 并且传入属于该实例的配置信息.
//创建新的实例
const axiosInstance = axios.create({
baseURL: ‘http:/ /123.207.32.32:8000’,
timeout: 5000,
headers: {
‘Content-Type’ : 'application/x-www-form-urlencoded ’
}
})
//发送网络请求
axiosInstance({
url: ‘/category’,
method: ‘get’
}).then(res => {
console. log(res);
}).catch(err => {
console. log(err);
})
axios封装:
import originAxios from ‘axios’
export default function axios(option) {
return new Promise((resolve, reject) =>{
//1.创建axios的实例
const instance = originAxios.create({
baseURL: ‘/api’,
timeout: 5000,
headers:‘’
});
//2.传入对象进行网络请求
instance(option).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
axios拦截器:
axios提供了拦截器,用于我们在发送每次请求或者得到相应后,进行对应的处理。
如何使用拦截器呢?
//配置请求和响应拦截
instance.interceptors.request.use(config =>{
console.log(‘来到了request拦截success中’);
return config
}, err => {
console.log(‘来到了request拦截failure中’);
return err
}
instance.interceptors.response.use(response =>{
console.log(‘来到了response拦截success中’);
return response.data
}, err =>{
console.log(‘来到了response拦截failure中’);
return err
})
拦截器中都做什么呢?
①请求拦截中错误拦截较少,通常都是配置相关的拦截。可能的错误比如请求超时,可以将页面跳转到一个错误页面中。
②响应拦截中完成的事情:
<1>响应的成功拦截中,主要是对数据进行过滤。
<2>响应的失败拦截中,可以根据status判断报错的错误码,跳转到不同的错误提示页面。
//请求拦截
instance.interceptors.request.use(config =>{
console.log(‘来到了request拦截success中’);
//1.当发送网络请求时,在页面中添加一个loading组件,作为动画
//2.某些请求要求用户必须登录,判断用户是否有token,如果没有token跳转到login页面
//3.对请求的参数进行序列化
config.data = qs.stringify (config.data)
console.log(config);
//4.等等
return config
})
//响应的成功拦截
instance.interceptors.response.use(response => {
console.log(‘来到了response拦截success中’);
return response.data
})
//响应的失败拦截
},err =>{
console.log(‘来到了response拦截failure中’);
if (err && err.response) {
switch (err.response.status) {
case 400:
err.message =‘请求错误’
break
case 401:
err.message =‘未授权的访问’
break
}
}
return err
防抖和节流:
本质上是优化高频率执行代码的一种手段。如:浏览器的 resize、scroll、keypress、mousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能。为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用throttle(防抖)和debounce(节流)的方式来减少调用频率。
定义:
①节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
②防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
比喻:
①想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应。
②假设电梯有两种运行策略 debounce 和 throttle,超时设定为15秒,不考虑容量限制。
③电梯第一个人进来后,15秒后准时运送一次,这是节流。
④电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖。
Vue 没有内置支持防抖和节流,但可以使用 Lodash 等库来实现。
----如果某个组件仅使用一次,可以在 methods 中直接应用防抖:----
自定义指令:
现在让我们用指令来实现这个功能:
const app = Vue.createApp({})
// 注册一个全局自定义指令 v-focus
app.directive(‘focus’, {
// 当被绑定的元素挂载到 DOM 中时……
mounted(el) {
// 聚焦元素
el.focus()
}
})
如果想注册局部指令,组件中也接受一个 directives 的选项:
directives: {
focus: {
// 指令的定义
mounted(el) {
el.focus()
}
}
}
然后你可以在模板中任何元素上使用新的 v-focus attribute,如下:
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
①created:在绑定元素的 attribute 或事件监听器被应用之前调用。在指令需要附加在普通的 v-on 事件监听器调用前的事件监听器中时,这很有用。
②beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用。
③mounted:在绑定元素的父组件被挂载后调用。
④beforeUpdate:在更新包含组件的 VNode 之前调用。
⑤updated:在包含组件的 VNode 及其子组件的 VNode 更新后调用。
⑥beforeUnmount:在卸载绑定元素的父组件之前调用
⑦unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次。
动态指令参数:指令的参数可以是动态的。例如,在 v-mydirective:[argument]=“value” 中,argument参数可以根据组件实例数据进行更新!这使得自定义指令可以在应用中被灵活使用。
const app = Vue.createApp({})
app.directive(‘pin’, {
mounted(el, binding) {
el.style.position = ‘fixed’
// binding.value 是我们传递给指令的值——在这里是 200
el.style.top = binding.value + ‘px’
}
})
app.mount(‘#dynamic-arguments-example’)
函数简写:
app.directive(‘pin’, (el, binding) => {
el.style.position = ‘fixed’
const s = binding.arg || ‘top’
el.style[s] = binding.value + ‘px’
})
对象字面量:如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。
app.directive(‘demo’, (el, binding) => {
console.log(binding.value.color) // => “white”
console.log(binding.value.text) // => “hello!”
})
Object.defineProperty()简介:
Object是在javascript中一个被我们经常使用的类型,而且JS中的所有对象都是继承自Object对象的。虽说我们平时只是简单地使用了Object对象来存储数据,并没有使用到太多其他功能,但是Object对象其实包含了很多很有用的属性和方法,尤其是ES5增加的方法,今天我们先探讨一下Object.defineProperty()。
Object.defineProperty 给一个对象添加或者修改属性 返回的是一个对象
①语法:Object.defineProperty(obj, prop, descriptor)
②参数:
<1>obj要在其上定义属性的对象。
<2>prop要定义或修改的属性的名称。
<3>descriptor将被定义或修改的属性描述符。
属性描述符是一个对象,参数如下:
①value: 设置属性值
②writeable: 设置当前属性是否允许被修改
③configurable:设置当前属性是否可以删除
④enumerable:设置当前属性是否可被枚举
⑤getter—get() 当获取属性值的时候触发的函数
⑥setter—set() 当设置属性的时候触发的函数
注意:当使用了get()方法或者set()方法的时候就不能使用value和writable中的任何一个属性否则会报错
例子:
①另一种方法是将库添加到vue原型中。所有组件都继承自此,因此它们现在都可以通过this关键字访问库。
import _ from ‘lodash ‘;
object.defineProperty(Vue.prototype,’$_’, { value: _ });
VSCode开发简介:
Vue开发简介:
NodeJS命令:
打开 package.json 文件观察scripts字段下是否有serve字段或者build字段。-g 是全局安装,不带 -g 会安装在个人文件夹-S 与 --save 的简写,安装包信息会写入 dependencies 中-D 与 --save-dev 的简写,安装包写入 devDependencies 中先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦