Chapter0 初识
MVVM(Model View ViewModel)
Vue的生命周期
生命周期:事物从诞生到消亡的整个过程
ES6补充
列表展示v-for
后面给数组追加元素时,新的元素也可以渲染出来
Chapter1 Vue基础语法
1.2插值操作
Mustache语法
不仅可以直接写变量,也可以写简单的表达式
v-once指令
只在第一次展示数据,当数据发生修改后展示的值不会相应修改
v-html指令
可以将内容转换为html内容输出
v-text指令
可以实现mustache的效果,但是会覆盖原来的文本
v-pre指令
使内容原封不动地展示出来而不做任何解析
<h2>{{message}}</h2>
<h2 v-pre>{{message}}</h2>
v-cloak
在vue解析之前div中有一个v-cloak属性, 直到vue解析,div中v-cloak属性会自动删除
1.3 v-bind
- 实现动态绑定属性(基本属性:src,href等)
- 语法糖:v-bind:value="" => :value=""
- 动态绑定class(对象语法{类名:boolean},数组语法)
- 动态绑定Style(对象语法{},数组语法)
1.4计算属性computed
获取各种属性,本质上就是一个属性而非函数,因此使用时不需要加括号
setter()和getter()
计算属性其实是一个对象,对象中有setter()和getter()方法 一般情况下没有setter()方法,此时计算属性是一个只读属性 getter()方法的返回值就是计算属性的属性值 因此可以使用语法糖:
fullName(){
return this.firstName + ' ' + lastName
}
计算属性和methods的对比
计算属性在浏览器中具有缓存,每次浏览器页面发生改变时都会将计算属性与原来的值进行对比:若发生改变则重新调用函数,若未发生改变则无需重新调用函数 因此,计算属性在多次使用时只会调用一次 而methods方法每次都要重新调用整个函数
1.5事件监听
语法糖:v-on:click="method" => @click="method" 在事件监听时,若函数没有参数需要传递则可以省略括号 如果函数需要传入参数而事件监听时省略了小括号,则Vue会将浏览器产生的event对象作为参数传入 方法定义时如果需要同时传入event和其他参数时,可以使用$event手动获取浏览器产生的event对象
修饰符
- .stop修饰符可以阻止事件的冒泡
- .prevent修饰符可以阻值默认事件的发生
- .监听键盘的某个键(如enter键) @keyUp.enter="keyUp"
- .once修饰符可以使事件监听的触发函数只触发一次
- .native
1.6条件判断
v-if = "Boolean" v-else-if = "Boolean" v-else 根据不同的条件选择不同页面的显示
v-show = "Boolean" v-show 为false时,元素的display属性设置为none 而v-if为false时,元素根本就不会存在在DOM中 因此,当我们需要在显示与隐藏间反复多次进行切换时选用v-show,而如果只需要少次切换时则使用v-if
1.7循环遍历
遍历数组
- 仅遍历数组内的元素,而不遍历索引值 v-for="value in arr"
- 遍历元素和索引 v-for="(value,index) in arr"
遍历对象
- 仅遍历对象内的值 v-for = "value in obj"
- 遍历键值对 v-for = "(value,key) in obj"
- 遍历键值对和索引 v-for = "(value,key,index) in obj"
数组中哪些方法是响应式的
- push() 向数组末端添加元素,可以一次添加多个元素
- pop() 删除数组末端元素
- shift() 删除数组的第一个元素
- unshift() 向数组最前面添加元素,也可以一次添加多个元素
- splice(a,b,c) 从第a个元素开始删除b个元素,在a之前添加元素c
- sort() 排序
- reverse() 反转
Vue.set(要修改的对象,索引值,修改后的值)(响应式) Vue.set(this.arr,0,'bbb')
通过索引值改变元素(非响应式)
1.8书籍购物车案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>书籍购物车</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="app">
<div v-if="books.length">
<table>
<thead>
<tr>
<th></th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in books">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<td>{{item.price | showPrice}}</td>
<td>
<button @click="sub(index)" v-bind:disabled="item.count <= 1">-</button> {{item.count}}
<button @click="add(index)">+</button>
</td>
<td>
<button @click="removeH(index)">移除</button>
</td>
</tr>
</tbody>
</table>
<h2>总价格:{{totalPrice | showPrice}}</h2>
</div>
<h2 v-else>购物车为空</h2>
</div>
<script src="../js/vue.js"></script>
<script src="./main.js"></script>
</body>
</html>
const app = new Vue({
el: '#app',
data: {
books: [
{ id: 1, name: '《算法导论》', date: '2006-9', price: 85, count: 1 },
{ id: 2, name: '《UNIX编程艺术》', date: '2006-2', price: 59, count: 1 },
{ id: 3, name: '《编程珠玑》', date: '2008-10', price: 39, count: 1 },
{ id: 4, name: '《代码大全》', date: '2006-3', price: 128, count: 1 },
],
},
methods: {
getFinalPrice(price) {
return '¥' + price.toFixed(2)
},
add(index) {
this.books[index].count++
},
sub(index) {
this.books[index].count--
},
removeH(index) {
this.books.splice(index, 1)
}
},
filters: {
showPrice(price) {
return '¥' + price.toFixed(2)
}
},
computed: {
totalPrice() {
let totalPrice = 0
for (let i of this.books) {
totalPrice += i.price * i.count
}
return totalPrice
}
}
})
table {
border: 1px solid #e9e9e9;
border-collapse: collapse;
border-spacing: 0;
}
th,
td {
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: center;
}
th {
background-color: #f7f7f7;
color: #5c6b77;
font-weight: 600;
}
1.9双向绑定
1.9.1基本使用与本质
v-model
<!-- 使用 v-model实现双向绑定 -->
<input type="text" v-model="message">
<!-- <input type="text" :value="message" @input="message = $event.target.value"> -->
1.9.2v-model和radio
具有相同name属性的选项互斥,而给选项绑定相同的v-model也可以达到相同的效果 通过给v-model设初值可以实现设置选项的默认值(在html中使用cheked属性),如不需设置默认值则将初值设为空字符串
1.9.3v-model和checkbox
- 通过在input外添加label,并将label的for与input的id设置为相同,可实现点击文字也可触发点击选框的效果
- checkbox单选框 v-model值为布尔值
- checkbox多选框 v-model值为数组
1.9.4v-model和select
- 选择一个 v-model值为字符串
- 选择多个 v-model值为数组
1.9.5修饰符
- .lazy修饰符可以使数据不再实时绑定,而是在敲回车或失去焦点时才绑定
- .number修饰符可以使v-model的赋值类型为Number而非String //input中键入数字 type="number"
- .trim修饰符可以将v-model的空格删除
Chapter2 组件化开发
组件的使用分三个步骤:
- 创建组件构造器
- 注册组件
- 使用组件
2.1全局组件和局部组件
2.2父组件和子组件
2.3组件注册的语法糖
2.4模板的分离写法
script
template
2.5数据的存放
- 子组件不能直接访问父组件的数据
- 子组件有自己的data,且必须是一个函数
- 为什么必须是一个函数?
组件之间相互影响
2.6父子组件的通信
父传子pros
子传父$emit
2.7项目
npm install npm run serve
2.8父子组件的访问
2.9slot
3模块化
3.1为什么要使用模块化
3.2ES6中模块化的使用
- export
- import
Chapter4 Webpack
4.1什么是 webpack
4.2webpack起步
4.3webpack的loader
4.4webpack配置Vue
4.5webpack的plugin
4.6搭建本地服务器
4.7配置文件的分离
Chapter5 Vue CLI详解
Command-Line Interface译为命令行界面,俗称脚手架
5.2 CLI2初始化项目的过程
5.3 CLI2生产的目录结构的解析
Chapter6 vue-router
🌏扩展笔记:
- 什么是前端渲染什么是后端渲染?
- 后端渲染阶段:jsp(java server page)/php 在后端通过各种技术直接将页面渲染完成再返回给前端并直接展示 (一个页面有自己的网址,就是url)前端将url发送到服务器,服务器对url(通过正则)进行匹配,然后通过控制器处理,生成 HTML和css代码返回给前端 后端路由:后端处理url和页面之间关系的路由
- 前后端分离阶段:随着Ajax出现,有了前后端分离的开发模式 后端只提供API来返回数据,前端通过Ajax获取数据,并通过JS渲染页面 当获取到url时,先去静态资源服务器中请求html+css+js代码,当执行js时发现api请求,再去服务器请求api相关资源,再根据这些资源对页面进行渲染 前端渲染:浏览器中显示的大部分内容都由前端js代码在浏览器中执行,最终渲染出来的网页
- 单页面富应用阶段(SPA--Single Page web Application):在前后端分离的基础上添加了前端路由 整个页面只有一个HTML页面,当url发生改变时整个页面不刷新,不再向服务器请求新的资源 前端路由:映射url->页面
- 如何改变页面的url却不使页面发生刷新(不向服务器发送新的请求)
- url的hash 直接修改hash
- history方法 history.pushState({},'','home'), history.back(), history.replaceState({},'','home'), history.go(-1), history.forward()
- 网址含义
🌏 URL:协议//localhost:端口/路径?查询 Scheme//host:port/path?query#fragment
vue-router基于路由和组件
router-link
tag="button" 设置router-link的样式为按钮(默认为 a标签) to="/home" 设置点击后url改变的值 点击时按钮会增添一个router-link-active类 class的名字可以通过class-active属性修改
代码跳转路由
动态路由
**this.$route.params.userId
路由的懒加载
打包时打包三个文件 app.js 自己写的代码 manifest.js 底层支撑的代码 vendor.js 第三方代码
懒加载:用到时再加载 将不同路由由不同组件分割成不同的代码块,当路由被访问时才加载对应组件 懒加载的方式:
- const Home = resolve =>{}...
- AMD写法 const About = resolve => require(['../components/About.vue'],resolve)
- ES6写法 const Home = () => import('../components/Home.vue')
嵌套路由
实现嵌套路由的步骤:
- 创建对应的子组件,并且在路由映射中配置对应的子路由
- 在组件内部使用标签
参数传递
传递参数主要有两种类型: params和query
params的类型
配置路由格式: /router/:id 传递的方式: 在path后跟上对应的值 传递后形成的路径: /router/123,/touter/abc
query的类型(传递对象)
配置路由格式: /router,也就是普通配置 传递的方式: 对象中使用query的key作为传递方式 传递后形成的路径: /router?id=123,/router?id=abc
router和route
任何一个组件里的this.route是当前处于活跃的路由对象,具有参数params,query等
导航守卫
监听导航栏的变化
- 全局守卫
//设置导航(前置)守卫
router.beforeEach((to, from, next) => {
//从from跳转到to时执行(跳转前执行)
document.title = to.matched[0].meta.title
next()
})
//设置导航(后置)守卫
router.afterEach((to, from) => {
//从from跳转到to时执行(跳转后执行)
document.title = to.matched[0].meta.title
next()
})
- 路由独享守卫 在路由配置时直接定义beforeEnter守卫 进入之前(跳转之前之后,跳转之后之前)
- 组件内的守卫
keep-alive
keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态或避免被重新渲染 router-view也是一个组件,如果直接被包在keep-alive里面,所有路径匹配到的视图组件都会被缓存
Chapter7 Vuex详解
Vuex是一个专为Vue.js应用程序开发的状态管理模式
- 把需要多个组件共享的变量全部存储在一个对象里
- 然后将这个对象放在顶层的Vue实例里,让其他组件可以使用
🌏哪些状态需要管理呢?
- 用户的登录状态、用户名称、头像、地理位置信息等
- 商品的收藏、购物车中的物品等
- 响应式,需要共享的
Chapter8 网络封装axios
Vue中发送网络请求有非常多的方式
- 传统的Ajax是基于XHR (配置和调用方式非常混乱)
- jQuery-Ajax (Vue中不需要jQuery,得不偿失)
- Vue-resourse (Vue2.x之后已不再维护)
- 🌟axios
Chapter9 项目实践
- 划分目录结构 assets(资源) imgs css common(公共的常量和方法) const.js utils.js components(公共的组件): common(其他项目里也会用到的组件) content(仅在当前项目中会用到的公共组件) network() router store view(各个主要的视图)
- css文件的引入
vue2中组件不能直接监听事件,需要添加.native
<back @click.native="backClick"></back>
vue3中则可以直接监听
不使用v-bind绑定的props会传递字符串,绑定之后则可以传递各种类型的数据
事件总线$bus
防抖节流
- 防抖debounce
debounce(func, delay) {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
- 节流throttle
tab-control吸顶效果
-
必须直到滚动到多少时开始有吸顶效果(获取到tab-control的offsetTop)
- 但不能直接在mounted中获取该值,在mounted中的值并没有将图片高度计算在内
- 因此要监听HomeSwiper中img的加载完成
- 加载完成后发出事件,并在Home.vue中获取正确的值
- 为了不让HomeSwiper多次发出事件,可以使用一个isLoad变量记录状态
-
利用两个tabControl组件实现“假动画”
Home离开时状态记录
-
keep-alive
-
让Home中内容保持
- 离开时保存一个位置信息saveY
跳转至商品详情页
- 创建新组件,绑定路由并设置点击跳转事件
- this.iid = this.$route.params.iid
- 搭建详情页
搭建详情页
导入navbar
- 导入DetailNavBar DetailNavBar 中导入NavBar
- 设置title与back
请求数据及轮播图展示
- Detail也keep-alive,要使用exclude将其剔除,则需要为组件设置name属性
混入mixin
toast弹窗
Chapter10 项目部署
服务器:一台没有显示器的电脑,24小时开机为用户提供服务 下载nginx 最新stable版本
将自己的电脑作为服务器
git add .
git commit -m '初始化项目'
git push
面试题
Vue响应式原理
- 数据更新页面跟着更新其实不是理所当然的
- app.message修改数据,Vue内部是如何监听message数据改变的?
Object.defineProperty -> 监听对象属性的改变
- 当数据发生改变,Vue是如何通知哪些人页面发生刷新?
发布订阅者模式
\