一、Vue的基本语法
1.Vue的安装方式
方式一:直接CDN引入
<!-- 开发环境版本,包含了有帮助的命令行警告-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/uve.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
方式二:下载和引入
开发环境 vuejs.org/js/vue.js
生产环境 vuejs.org/js/vue.min.…
方式三:NPM安装
后续通过webpack和CLI的使用,我们使用该方式。
2.Vue的使用案例
- vue的基本使用方式

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
<h2>{{ name }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
//编程方式: 声明式编程
const app = new Vue({
el: '#app', //用于挂在要管理的元素
data: { //定义数据
message: '你好啊,李银河',
name: 'coderwhy'
}
});
// 元素js的做法(编程范式: 命令式编程)
// 1.创建div元素,设置id属性
// 2.定义一个变量叫message
// 3.将message变量放在前面的div元素中显示
// 4.修改message的数据: 今天天气不错!
// 5.将修改后的数据再次替换到div元素
</script>
</body>
</html>

- 列表展示

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in movies">{{ item }}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
movies: ['星际穿越', '大话西游', '少年派', '盗梦空间']
}
});
</script>
</body>
</html>

- 计数器示例

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>当前计数: {{ counter }}</h2>
<!-- <button v-on:click="counter++">+</button>
<button v-on:click="counter--">-</button> -->
<button v-on:click="add">+</button>
<button v-on:click="sub">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
add: function () {
console.log('add被执行');
this.counter++;
},
sub: function () {
console.log('sub被执行');
this.counter--;
}
}
});
// 1.拿button元素
// 2.添加监听事件
</script>
</body>
</html>

3.Vue示例传入的options
- el:类型:string | HTMLElement(决定之后Vue示例会管理哪一个DOM)
- data:类型:Object | Function组件当中data必须是一个函数(Vue实例对应的数据对象)
- methods:类型{[key:string]:Function}(定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用)
4.Vue的生命周期(事物从诞生到消亡的整个过程)

5.插值操作
- mustache{{}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<h2>{{ message }}</h2>
<h2>{{ message }}, 李银河!</h2>
<!-- mustache语法中,不仅仅可以直接写变量,也可以写简单的表达式-->
<h2>{{ firstName + lastName }}</h2>
<h2>{{ firstName + ' ' + lastName }}</h2>
<h2>{{ firstName }} {{ lastName }}</h2>
<h2>{{ counter * 2 }}</h2>
</div>
<script> src = '../js/vue.js'</script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
firstName: 'kobe',
lastName: 'bryant',
counter: 100
}
});
</script>
</body>
</html>
- v-once:该指令后不用加表达式(表示元素和组件只渲染一次,不会随着数据的改变而改变)。
- v-html:后面往往会跟上一个string类型(将string的html解析出来并且进行渲染)
- v-text:作用和Mustache比较相似,用于将数据显示在界面中(通常情况下,接收一个string类型)
- v-pre:将{{ message }}不解析
- v-cloak:防止浏览器直接显示出未解析的mustache表达式(在渲染前存在,渲染后不存在)
6.绑定操作
- v-bind:any | Object(动态绑定一个属性)可以简写为语法糖:
********v-bind绑定class********
用法一:直接通过{}绑定一个类
<h2 :class="{'active':isActive}">Hello World</h2>
用法二:也可以通过判断,传入多个值
<h2 :class="{'active':isActive, 'line':isLine}">Hello World</h2>
用法三:和普通的类同时存在,并不冲突
注:如果isActive和isLine都为true,那么会有title/active/line三个类
<h2 class="title" :class="{'active':isActive, 'line':isLine}">Hello World</h2>
用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello World</h2>
********v-bind绑定style********
<div :style="{color: currentColor, fontSize: fontSize + 'ps'}"></div>
style后面跟的是一个对象类型
<div v-bind:style="[baseStyles, overridingStyles]"></div>
style后面跟的是一个数组类型
7.计算属性(computed)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<!-- 1.直接拼接:语法过于繁琐-->
<h2>{{ firstName }} {{ lastName }}</h2>
<!-- 2.通过定义methods,多次调用会多次执行 -->
<h2>{{ getFullName() }}</h2>
<h2>{{ getFullName() }}</h2>
<h2>{{ getFullName() }}</h2>
<h2>{{ getFullName() }}</h2>
<h2>{{ getFullName() }}</h2>
<!-- 3.通过computed,通过缓存只执行一次 -->
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
</div>
<script src='../js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Lebron',
lastName: 'James'
},
computed: {
fullName: function() {
console.log('fullName');
return this.firstName + ' ' + this.lastName;
}
},
methods: {
getFullName: function() {
console.log('getFullName');
return this.firstName + ' ' + this.lastName;
}
}
});
</script>
</body>
</html>
8.事件监听
v-on(语法糖@):如果不需要参数可以不写(),如果有一个参数默认将event传过去。
****** 参数相关 ******
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<!-- 时间调用的方法没有参数 -->
<button @click="btn1Click()">按钮1</button>
<button @click="btn1Click">按钮1</button>
<!-- 在时间定义时,写函数时省略了小括号,但是方法本身是需要一个参数的 -->
<button @click="btn2Click(123)">按钮2</button>
<!-- <button @click="btn2Click()">按钮2</button> -->
<button @click="btn2Click">按钮2</button>
<!-- 方法定义时,我们需要event对象,同时又需要其他参数 -->
<button @click="btn3Click(123, $event)">按钮3</button>
<button @click="btn3Click(123)">按钮4</button>
</div>
<script src='../js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
methods: {
btn1Click() {
console.log('btn1Click');
},
btn2Click(event) {
console.log(event);
},
btn3Click(num, event) {
console.log(num);
console.log(event);
}
}
});
</script>
</body>
</html>
****** 修饰符 ******
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<!-- 1..stop修饰符的使用(防止冒泡) -->
<div @click="divClick">
Div HTMLElement
<button @click.stop="btnClick">按钮</button>
</div><br>
<!-- 2..prevent修饰符的使用(阻止默认事件) -->
<form action="baidu">
<input type="submit" value="提交" @click.prevent="submitClick">
</form>
<!-- 3.. 监听某个键盘的键帽-->
<input type="text" @keyup.enter="keyUp">
<!-- 4..once修饰符的使用(只触发一次回调) -->
<button @click.once="btn2Click">按钮2</button>
</div>
<script src='../js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
methods: {
divClick() {
console.log('divClick');
},
btnClick() {
console.log('btnClick');
},
btn2Click() {
console.log('btnClick');
},
submitClick() {
console.log('submitClick')
},
keyUp() {
console.log('keyUp');
}
}
});
</script>
</body>
</html>
9.v-if、v-else、v-else-if
会根据key判断是否复用(即当前dom的唯一标识)

10.v-show

11.v-for循环遍历
- 遍历数组

- 遍历对象

- 绑定一个唯一的key可以提高性能(Diff算法)

- 可以响应式渲染页面的数组方法

12.v-model的使用
- v-model双向绑定的原理
1.绑定了对应dom的value值
2.绑定了对应dom的input事件

- v-model结合checkbox的使用

- v-model结合select的使用

- v-model修饰符的使用

13.组件化开发
- 组件的基本使用

- 父组件和子组件

- 组件的语法糖注册方式

- 组件模块的分离写法

- 组件通信-父组件向子组件传递数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id='app'>
<cpn :cmovies="movies" :cmessage="message"></cpn>
</div>
<template id="cpn">
<div>
<ul>
<li v-for="item in cmovies">{{ item }}</li>
</ul>
<h2>{{ cmessage }}</h2>
</div>
</template>
<script src='../js/vue.js'></script>
<script>
// 父传子: props
const cpn = {
template: '#cpn',
// props: ['cmovies', 'cmessage'],
props: {
// 1.类型限制
// cmovies: Array,
// cmessage: String
// 2.提供一些默认值
cmessage: {
type: String,
default: '',
// 必须值
required: true,
validator() {
return ['success','warning','danger'].indexOf(value) !== -1;
}
},
// 类型是对象或者数组时,默认值必须是一个函数
cmovies: {
type: Array,
default() {
return []
}
}
},
data() {
return {}
},
methods: {
}
};
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
movies: ['海王', '海贼王', '海尔兄弟']
},
components: {
cpn
}
});
</script>
</body>
</html>
- 组件通信-子传父
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- 父组件模板 -->
<div id='app'>
<cpn @itemclick="cpnClick"></cpn>
</div>
<!-- 子组件模板 -->
<template id="cpn">
<div>
<button @click="btnClick(item)" v-for="item in categories">{{ item.name }}</button>
</div>
</template>
<script src='../js/vue.js'></script>
<script>
// 1.子组件
const cpn = {
template: '#cpn',
data() {
return {
categories: [
{id:'aaa', name:'热门推荐'},
{id:'bbb', name:'手机数码'},
{id:'ccc', name:'家装家电'},
{id:'ddd', name:'电脑办公'}
]
}
},
methods: {
btnClick(item) {
//发射事件
this.$emit('itemclick', item);
}
}
}
// 2.父组件
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
components: {
cpn
},
methods: {
cpnClick(item) {
console.log(item);
}
}
});
</script>
</body>
</html>
-
父子组件的访问方式($children)-父访问子

-
父子组件的访问方式(
root)-子访问父

14.组件的插槽(slot)
- 插槽的基本使用

- 具名插槽的使用

- 作用域插槽(父组件获取子组件元素)

二、webpack详解
1.webpack的安装
- 查看自己的node版本

- 全局安装webpack

- 局部安装webpack --save-dev是开发时依赖,项目打包后不需要继续使用的

2.webpack的起步

****** info.js(使用ES6的模块化导入) ******
export const name = 'why';
export const age = 18;
export const height = 1.88;
****** mathUtils.js(使用commonJs的模块化导入) ******
function add(num1, num2) {
return num1 + num2;
}
function mul(num1, num2) {
return num1 * num2;
}
module.exports = {
add,
mul
}
****** main.js实际调用的类 ******
const {add, mul} = require('./mathUtils.js');
console.log(add(20, 30));
console.log(mul(20, 30));
import { name, age, height } from './info';
console.log(name);
console.log(age);
console.log(height);
****** index.html ******
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="./dist/bundle.js"></script>
</body>
</html>
打包成对应的bundle

3.webpack的配置
- 创建webpack.config.js文件

const path = require('path');
module.exports = {
entry: './src/main.js',
output: {
//动态获取路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
}
****** 可以直接执行webpack命令 ******
-
node包的管理文件(通过npm init命令生成)

-
package.json中的script可以通过npm run命令执行定义的命令

4.webpack的loader
- 可以查询以下网站查找相应的loader www.webpackjs.com/loaders/css…
- 以解析css的loader为例执行如下命令

- 添加配置文件信息

5.webpack配置Vue
-
安装vue

-
配置webpack文件

-
下载vue文件的解析loader

{
test: /\.vue$/,
use: ['vue-loader']
},
6.配置webpack插件
-
添加打包文件版权描述信息插件

-
指定根据什么模板文件来生成index.html 下载html-webpack-plugin插件

生成后的index.html文件

-
压缩js文件代码 下载uglifyjs-webpack-plugin插件
添加配置信息

-
搭建本地服务器 安装webpack-dev-server
配置执行命令

7.webpack配置文件的抽离
- 将webpack的配置信息分成三个文件
base.config.js:公共的配置信息
dev.config.js:开发环境的配置信息
prod.config.js:生产环境的配置信息
下载webpack-merge插件
将公共配置信息和开发或生产环境的配置文件合并

三、Vue CLI(脚手架使用)
1.安装Vue脚手架
- 安装vue最新版本

- 安装vue2.x版本

2.Vue2.x脚手架的使用

3.vue+complier和vue-only的区别
vue+complier:template->ast->render->vdom->UI
vue-only:render->vdom->UI(通过下载的vue-template-complier将template直接解析成render了)
4.Vue3.x脚手架的使用
指定下载3.2.1版本的脚手架指令


5.修改Vue3.x脚手架的配置方式
启动可视化配置项目

四、路由的使用(vue-router)
1.vue-router的基本使用
- 安装vue-router

- 配置router文件,并将router组件挂在到App.vue中


2.vue-router的嵌套路由

3.vue-router的参数传递
- 通过:to的方式跳转并传递数据



- 通过按钮事件的方式跳转并传递数据

4.vue-router的导航守卫(beforeEach() | afterEach())

5.keep-alive

- keep-alive -> activated/deactivated
- 首页中使用path属性记录离开时的路径,在beforeRouteLeave中记录。
- keep-alive的属性 include-字符串或正则,只有匹配的组件会被缓存 exclude-字符串或正则,任何匹配的组件都不会被缓存
五、Promise的使用
1. Promise的基本使用
// 1.使用setTimeout
// setTimeout(() => {
// console.log('Hello World');
// }, 1000)
// 参数 -> 函数(resolve, reject)
// resolve, reject本身它们又是函数
// 链式编程
new Promise((resolve, reject) => {
// 第一次网络请求的代码
setTimeout(() => {
resolve();
}, 1000)
}).then(() => {
// 第一次处理代码
console.log('Hello World');
return new Promise((resolve, reject) => {
// 第二次网络请求的代码
setTimeout(() => {
resolve();
}, 1000)
})
}).then(() => {
// 第二次处理代码
console.log('Hello Vuejs');
return new Promise((resolve, reject) => {
// 第三次网络请求的代码
setTimeout(() => {
resolve();
}, 1000)
})
}).then(() => {
// 第三次处理代码
console.log('Hello End');
});
// 什么情况下会用到Promise?
// 一般情况下是有异步操作时,使用Promise对这个异步操作进行封装
// new -> 构造函数(1.保存一些状态信息 2.执行传入的函数)
// 在执行传入的回调函数时,会传入两个参数,resolve,reject,本身又是函数
new Promise((resolve, reject) => {
setTimeout((data) => {
// 成功的时候调用reslove
resolve('Hello World')
// 失败的时候调用reject
reject('error message');
}, 1000)
}).then(data => {
console.log(data);
}).catch(err => {
console.log(err);
});
// 或者可以不用catch只使用then获取error信息
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello World");
reject("Error Data");
}, 1000)
}).then(data => {
console.log(data);
}, error => {
console.log(error);
});
2. Promise的链式调用(三种写法)
<script>
// 网络请求: aaa -> 自己处理(10行)
// 处理: aaa111 -> 自己处理(10行)
// 处理: aaa111222 -> 自己处理
// 第一种写法
// new Promise((resolve, reject) => {
// setTimeout(() => {
// resolve('aaa');
// reject('error')
// },1000)
// }).then(res => {
// console.log(res + '第一层的10行处理代码');
// return new Promise((resolve, reject) => {
// resolve(res + '111');
// reject('error')
// })
// }).then(res => {
// console.log(res + '第二层的10行处理代码');
// return new Promise((resolve, reject) => {
// resolve(res + '222');
// reject('error')
// })
// }).then(res => {
// console.log(res + '第三层的10行处理代码');
// }).catch(err => {
// console.log(err)
// });
// 第二种写法
// new Promise((resolve, reject) => {
// setTimeout(() => {
// resolve('aaa');
// }, 1000)
// }).then(res => {
// console.log(res + '第一层的10行处理代码');
// return Promise.resolve(res + '111');
// 两种抛出异常的方式
// return Promise.reject('error');
// throw 'error message'
// }).then(res => {
// console.log(res + '第二层的10行处理代码');
// return Promise.resolve(res + '222');
// return Promise.reject('error');
// }).then(res => {
// console.log(res + '第三层的10行处理代码');
// }).catch(err => {
// console.log(err);
// });
// 第三种写法(省略掉Promise.resolve直接对数据进行处理)
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa');
}, 1000)
}).then(res => {
console.log(res + '第一层的10行处理代码');
return res + '111';
}).then(res => {
console.log(res + '第二层的10行处理代码');
return res + '222';
}).then(res => {
console.log(res + '第三层的10行处理代码');
})
</script>
3.Promise的All方法
<script>
// 两次请求都执行完resolve方法后才调用then方法
Promise.all([
// new Promise((resolve, reject) => {
// $ajax({
// url: 'url1',
// success: function (data) {
// resolve(data);
// }
// })
// }),
// new Promise((resolve, reject) => {
// $ajax({
// url: 'url2',
// success: function (data) {
// resolve(data);
// }
// })
// })
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('result1');
}, 2000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('result2');
}, 1000)
})
]).then(results => {
console.log(results[0]);
console.log(results[1]);
})
</script>
六、Vuex详解
1.安装Vuex
- 执行vuex插件安装命令

- 新建vuex配置文件的目录及文件

- 添加vuex配置文件代码
import Vue from 'vue';
import Vuex from 'vuex';
// 1.安装插件
Vue.use(Vuex);
// 2.创建对象
const store = new Vuex.Store({
state: {
counter: 1000
},
mutations: {
},
actions: {
},
getters: {
},
modules: {
}
});
// 3.导出store独享
export default store;
- 在Vue实例中注册

2. Vuex的使用

七、axios请求框架详解
1.axios的基本使用

2.axios发送并发请求

3.axios全局配置

4.axios实例

5.axios拦截器(请求成功,请求失败,响应成功,响应失败)
export function request(config) {
// 1.创建axios的实例
const instance = axios.create({
baseURL: 'http://123.207.32.32:8000',
timeout: 5000
})
// 2.axios的拦截器
// 2.1请求拦截的作用
instance.interceptors.request.use(config => {
console.log(config);
// 1.比如config中的一些配置信息不符合服务器要求
// 2.比如每次发送网络请求时,都希望在页面中显示一个请求的图标
// 3.某些网络请求(比如登陆(token)), 需要携带一些特殊的信息
return config
}, err => {
// 断网的时候(发不出去)
console.log(err);
});
// 2.2响应拦截的作用
instance.interceptors.response.use(res => {
console.log(res);
return res.data;
}, err => {
console.log(err);
});
// 3.发送真正的网络请求
return instance(config);
}