Vue的声明周期
声明周期的函数
Vue中的指令
-
v-once : 只渲染一次,不会随着数据的改变而改变
-
v-html : 会将string的HTML解析出来并且渲染
-
v-text : 接受一个string类型,将数据显示在界面中
-
v-pre : 跳过这个元素和它子元素的编译过程,用于显示本地的Mustache语法
-
v-bind:
-
作用:动态绑定属性
-
缩写为 : (语法糖的形式)
-
v-bind动态绑定class
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>class</title> </head> <style> .active { color: red; } </style> <body> <div id="app"> <h2 :class="active">{{ message }}</h2> <h2 :class="{active: isActive}">{{ message }}</h2> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> const app = new Vue({ el : '#app', data: { message: "你好", active: 'active', isActive : true } }) </script> </html>
-
v-bind动态绑定style
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>style动态绑定</title> </head> <body> <div id="app"> <h2 :style="{'font-size' : finalSize}">{{ message }}</h2> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> const app = new Vue({ el : '#app', data: { message: "你好", finalSize: '100px' } }) </script> </body> </html>
-
-
v-on:事件监听,比如点击,拖拽,键盘事件等等
-
作用:绑定事件监听器
-
缩写 @ (语法糖的形式)
-
参数: event
- 如果方法不需要参数,方法后的()可以不添加
- 如果方法本身有一个参数,那么会默认将原生事件event参数传递进去
- 如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件
-
修饰符:Vue提供了修饰符来处理一些事件
- .stop - 调用event.stopPropagation()
- .prevent - 调用event.preventDefault()
- .native - 监听组件根元素的原生事件
- .once - 只触发一次回调
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修饰符</title> </head> <body> <div id="app"> <!-- stop修饰符的使用 --> <div @click="divClick"> aaaaa <button @click.stop = "btnClick">点击</button> </div> <!-- prevent修饰符的使用 --> <form action="baidu"> <input type="submit" value="提交" @click.prevent = "subClick"/> </form> <!-- 监听某个键盘的键帽 --> <!-- 不添加enter的时候按任意键都会激活 加入enter后只有按回车键才可以激活 --> <input type="text" @keyup.enter="keyup"> <!-- once修饰符的使用 --> <button @click.once="onceClick">按钮</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> const app = new Vue({ el: "#app", data: { message: '你好呀' }, methods: { btnClick() { console.log("btnClick"); }, divClick() { console.log("divClick"); }, subClick() { console.log("subClick"); }, keyup() { console.log("keyup"); }, onceClick() { console.log("onceClick"); } } }) </script> </body> </html>
-
计算属性
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>计算属性</title>
</head>
<body>
<div id="app">
<h5>{{ fullName }}</h5>
<h5>{{ fullName }}</h5>
<h5>{{ fullName }}</h5>
<h5>{{ fullName }}</h5>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firsrName: '阿修罗',
lastName: '剑圣'
},
computed: {
fullName: function () {
return this.firsrName + " " + this.lastName
}
}
})
</script>
</body>
</html>
计算属性复杂操作
setter和getter
<script>
const app = new Vue({
el: '#app',
data: {
firsrName: '阿修罗',
lastName: '剑圣'
},
computed: {
// fullName: function () {
// return this.firsrName + " " + this.lastName
// }
fullName: {
set: function () {
},
get: function () {
return this.firsrName + " " + this.lastName
}
}
}
})
</script>
对象字面量增强写法
条件判断
v-if的原理:
- v-if后面的条件为false时,对应的元素及其子元素不会被渲染
- 也就是根本不会有对应的标签出现在DOM中
案例小问题:
切换类型发现文字依然显示之前的输入的内容.
问题解答:因为在Vue进行渲染时,出于性能考虑,会尽可能的复用已经存在的元素.而不是创建新的元素
解决方案:不希望使用Vue出现类似重复使用的问题,可以给对应的input添加key,并且需要保持key的不同
v-show和v-if的区别
- v-if当条件为false时,压根不会有对应的元素在DOM中.
- v-show当条件为false时,仅仅是将元素的display属性设置为none而已
开发中如何选择:
- 当需要在显示和隐藏之间切换的很频繁时,使用v-show
- 当只有一次切换时,通过使用v-if
数组中响应式方法
- push() : 在数组的结尾加入值
- pop() : 删除数组中的最后一个元素
- shift() : 删除数组中的第一个元素
- unshift() : 在数组最前面加入元素
- splice() : 删除元素/插入元素/替换元素
- sort() : 排序
- reserve () : 反转
JavaScript中的高阶函数
filter
const nums = [10, 20, 30, 50, 666, 7]
let newNums = nums.filter(function (n) {
return n < 100
})
console.log(newNums)
- filter中的回调函数有一个要求,必须返回一个boolean值
- true : 当返回true时,函数内部会自动将这次回调的n加入到新的数组中
- false: 当返回false时, 函数内部会过滤这次的n
map
reduce
对数组的内容进行汇总
v-model双向绑定
v-model原理
v-model其实是一个语法糖,它的背后本质包含两个操作:
- v-bind绑定一个value时间
- v-on指令给当前元素绑定input事件
<input type="text" v-model="message">
<!-- 等同于下列代码 -->
<input type="text" v-bind="message" v-on:input="message = $event.target.value">
v-model的修饰符
lazy修饰符
- 默认情况下,v-model默认是在input事件中同步输入框的数据的
- lazy修饰符可以让数据在失去焦点或者是回车时才会更新
number修饰符
- 默认情况下,在输入框中无论输入的书数字还是字母,都会被当作字符串来进行处理
- number修饰符可以让在输入框中输入的内容自动转换为数字类型
trim修饰符
- 如果输入的内容收尾有很多的空格,通常我们希望将其去除
- trim修饰符可以过滤内容左右边的空格
组件化开发
组件化的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件的使用</title>
</head>
<body>
<div id="app">
<my></my>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 创建组件构造器
const myComponent = Vue.extend({
template:
`<div>
<h2>组件标题</h2>
<p>组件中的一段内容</p>
</div>`
});
// 注册组件
Vue.component('my', myComponent);
const app = new Vue({
el: "#app"
})
</script>
</body>
</html>
父组件和子组件
<script>
const comC1 = Vue.extend({
template:
`
<div>
<h2>阿修罗</h2>
<p>今天的天气很好</p>
</div>
`
});
const comC2 = Vue.extend({
template:
`
<div>
<h2>子组件</h2>
<p>子组件注册完成</p>
<com1></com1>
</div>
`,
components: {
com1: comC1
}
});
const app = new Vue({
el: "#app",
components: {
com2: comC2
}
})
</script>
注册组件的语法糖格式
<script>
const comC2 = Vue.extend({
template:
`
<div>
<h2>子组件</h2>
<p>子组件注册完成</p>
<com1></com1>
</div>
`,
components: {
"com1": {
template:
`
<div>
<h2>阿修罗</h2>
<p>今天的天气很好</p>
</div>
`
}
}
});
const app = new Vue({
el: "#app",
components: {
com2: comC2
}
})
</script>
父子组件间的通信
父子组件之间的通信:
- 通过props向子组件传递数据
- 通过事件向父组件发送信息
props基本用法:
props的值有两种方式:
- 方式一:字符串数组,数组中的字符串就是传递的名称.
- 方式二:对象,对象可以设置传递时的类型,也可以设置默认值等
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父组件向子组件传递数据</title>
</head>
<body>
<div id="app">
<tem v-bind:cmessage="message" :cmovies="movies"></tem>
</div>
<template id="tem">
<div>
<h2>{{ cmessage }}</h2>
<ul>
<li v-for="movie in cmovies">{{ movie }}</li>
</ul>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
message: "阿修罗",
movies: ["异星灾难", "三体", "权利的游戏"]
},
components: {
"tem" : {
template: "#tem",
// 以数组的方式传递
// props: ["cmessage", "cmovies"]
props: {
// 类型限制
// cmessage: String,
// cmovies: Array
// 提供一些默认值
cmessage: {
type: String,
default: "没有传值",
required: true
},
cmovies: {
type: Array,
default: ["西游记", "三国演义", "水浒传"],
required: true
}
}
}
}
})
</script>
</body>
</html>
子组件向父组件传递数据:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>子组件向父组件传递数据</title>
</head>
<body>
<div id="app">
<cpn @itemclick="cpnClick"></cpn>
</div>
<template id="cpn">
<div>
<button v-for="item in categories"
@click="btnClick(item)">
{{ item.name }}
</button>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
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)
}
}
}
const app = new Vue({
el: "#app",
data: {
},
methods: {
cpnClick(item) {
console.log("cpnClick", item);
}
},
components: {
cpn
}
})
</script>
</body>
</html>
父子组件的访问方式
访问方式:
-
父组件访问子组件: 使用$children或者是refs
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>父组件访问子组件</title> </head> <body> <div id="app"> <cpn ref="aaa"></cpn> <cpn ref="cpn"></cpn> <button @click="btnClick">点击出现</button> </div> <template id="tem"> <div>我是子组件</div> </template> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> const app = new Vue({ el: "#app", methods: { btnClick() { // console.log(this.$children); // console.log(this.$children[0].showMessage); console.log(this.$refs.aaa); } }, components: { cpn: { template: "#tem", methods: { showMessage() { console.log("showMessage"); } } } } }) </script> </body> </html>
-
子组件访问父组件: 使用$parent(不建议使用)
slot插槽
插槽的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn><button>新加按钮</button></cpn>
<cpn><span>天气</span></cpn>
<cpn>
<div>阿修罗</div>
</cpn>
</div>
<template id="tem">
<div>
<h2>哈哈</h2>
<slot><button>默认按钮</button></slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
components: {
cpn: {
template: "#tem"
}
}
})
</script>
</body>
</html>
具名插槽的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn><span slot="right">替换右边</span></cpn>
<cpn><span slot="center">替换中间</span></cpn>
</div>
<template id="tem">
<div>
<slot name="left">左边</slot>
<slot name="center">中间</slot>
<slot name="right">右边</slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
components: {
cpn: {
template: "#tem"
}
}
})
</script>
</body>
</html>
作用域插槽使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn>
<template slot-scope="slot">
<span>{{ slot.data.join("-")}}</span>
</template>
</cpn>
<cpn>
<template slot-scope="slot">
<span>{{ slot.data.join("*")}}</span>
</template>
</cpn>
</div>
<template id="tem">
<div>
<slot :data="pLanguage">
<ul>
<li v-for="item in pLanguage">{{ item }}</li>
</ul>
</slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
components: {
cpn: {
template: '#tem',
data() {
return {
pLanguage: ["JavaScript", "C#", "java", "Go"]
}
}
}
}
})
</script>
</body>
</html>
webpack
npm管理node下的各种包
loader
webpack用来做什么?
- 在我们之前的实例中,我们主要使用webpack来处理我们写的js代码,并且webpack会自动处理js之间相关的依赖
- 但是在开发中不仅仅有基本的js代码处理,也需要加载css、图片、也包括一些高级的将ES6转成ES5代码,将Typescript转成ES5代码,将less转成css,将.jsx .vue 转成js文件
- 对于webpack本身来说这些转化是不支持的
loader的使用过程:
- 通过npm安装需要使用的loader
- 在webpack.config.js中的modules关键字下进行配置
plugin
使用步骤:
- 通过npm安装需要的plugins
- 在webpack.config.js中的plugins中配置插件
cli
runtime-compiler和runtime-only的区别
runtime-compiler的渲染过程:
template -> ast -> render -> vdom -> UI
runtime-only的渲染过程:
render -> vdom -> UI
vue-cli3与2的区别:
- vue-cli3是基于webpack4打造
- vue-cli3的设计原则是零配置,移除的配置文件根目录下的build和config等目录
- vue-cli3提供了vue ui命令,提供了可视化视图,更加人性化
- 移除了static文件夹,新增了public文件夹,并且index.html移动到public中
箭头函数
箭头函数的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>箭头函数</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 参数问题
// 两个参数
const sum = (num1, num2) => {
return num2 + num1
}
// 一个参数
const power = num => {
return num * num
}
// 返回值问题
// 函数代码块中只有一行代码
const mul = (num1, num2) => num1 * num2
console.log(mul(20, 30));
const demo = () => console.log("Hello World")
console.log(demo());
</script>
</body>
</html>
this的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>this的使用</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const obj = {
aaa() {
setTimeout(function () {
setTimeout(function (){
console.log(this) // this
})
setTimeout(() => {
console.log(this) // this
})
})
setTimeout(() => {
setTimeout(function () {
console.log(this) // this
})
setTimeout(() => {
console.log(this) // obj
})
})
}
}
obj.aaa()
</script>
</body>
</html>
vue-router
步骤一:安装vue-router
npm install vue-router --save
步骤二:
- 导入路由对象,并且调用Vue.use(VueRouter)
- 创建路由实例,并且传入路由映射配置
- 在Vue实例中挂载创建的路由实例
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
步骤三:
- 创建路由组件
- 配置路由映射:组件和路径映射关系
- 使用路由:通过和
router-link
router-link的一些其他属性:
- tag:可以指定之后渲染成什么组件,比如默认会被渲染成
- replace:repalce不会留下history记录,在指定replace的情况下,后退键返回不能返回到上一个页面中
- active-router:当对应的路由匹配成功会自动给当前元素设置一个router-link-active的class
路由的懒加载
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
// 重定向
redirect: '/Home'
},
{
path: '/home',
name: 'Home',
// 路由的懒加载
component: () => import("../components/Home")
},
{
path: '/about',
name: 'About',
// 路由懒加载
component: () => import("../components/About")
},
{
path: '/user/:userId',
name: 'User',
// 路由懒加载
component: () => import("../components/User")
}
],
// 将默认的hash模式改为history模式
mode: 'history'
})
参数传递方式
params类型
- 配置路由的格式: /router/:id
- 传递的方式:在path后面跟上对应的值
- 传递后形成的路径:/router/123,/router/abc
query类型
- 配置格式:/router.也就是普通配置
- 传递的方式:对象中使用query的key作为传递方式
- 传递后形成的路径:/router?id=123
TabBar
axios
axios中的并发:
axios.all([axios({
url: ""
}),axios({
url: "",
params: {
}
})]).then(res => {
})
封装方式
方式一
export function request(config) {
return new Promise((resolve, reject) => {
const instance = axios.create({
baseURL: "",
timeout: 5000
})
return instance(config)
})
}
方式二:
export function request(config) {
return new Promise((resolve, reject) => {
const instance = axios.create({
baseURL: "",
timeout: 5000
})
instance(config)
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
})
}
Promise
什么情况下可以用到?
一般情况下有异步操作时,使用Promise对操作进行封装
new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 2000)
}).then(() => {
console.log("hello world");
console.log("hello world");
console.log("hello world");
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 2000)
}).then(() => {
console.log("hello world");
console.log("hello world");
console.log("hello world");
})
})
promise的三种状态
- pending:等待状态,比如正在进行网络请求,或者是定时器没有到时间
- fulfill:满足状态,当我们主动调用resolve时,就处于该状态,并调用then()
- reject:拒绝状态,当我们主动调用reject时,就处于该状态并且会调用catch
Promise中all方法使用
Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => {
resolve({name: "张三", age: 18})
}, 2000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve({name: "kobe", age: 19})
}, 1000)
})
]).then(results => {
console.log(results);
})
Vuex
- state:驱动应用的数据源
- view:以声明方式将state映射到视图
- actions:响应在view上的用户输入导致的状态变化
Vuex状态管理图例
在mutations中改变数据
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
counter: 1000
},
mutations: {
// 定义方法
increment(state) {
state.counter ++
},
decrement(state) {
state.counter --
},
// mulations特殊的提交风格
incrementCount(state, payload) {
state.counter += payload.count
}
},
actions: {},
getters: {},
modules: {}
})
export default store
<template>
<div id="app">
<h2>{{ $store.state.counter }}</h2>
<button @click="incre">+</button>
<button @click="decre">-</button>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
message: "阿修罗"
}
},
methods: {
incre() {
this.$store.commit("increment")
},
decre() {
this.$store.commit("decrement")
},
addCopunt() {
// 特殊的提交封装
this.$store.commit({
type: "incrementCount",
count
})
}
}
}
</script>
getters的使用
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
counter: 1000,
students: [
{id: 1001, name: "hary", age: 18},
{id: 1002, name: "why", age: 19},
{id: 1003, name: "koba", age: 20},
{id: 1003, name: "curry", age: 21}
]
},
mutations: {
// 定义方法
increment(state) {
state.counter ++
},
decrement(state) {
state.counter --
}
},
actions: {},
getters: {
powerCounter(state) {
return state.counter * state.counter
},
getAgeMore20Stu(state) {
// return state.students.filter((s) => {
// return s.age > 20
// })
return state.students.filter((s => s.age > 20))
},
getStuLength(state, getters) {
return getters.getAgeMore20Stu.length
}
},
modules: {}
})
export default store