1. 库和框架的区别
库: 本质上是一些函数的集合。每次调用函数,实现一个特定的功能,接着把
控制权
交给使用者(程序猿)
- 代表:jQuery axios
- jQuery这个库的核心:DOM操作+对ajax的封装,即:封装DOM操作,简化DOM操作
- axios: 封装了对ajax的操作
框架: 是一套完整的解决方案,使用框架的时候,需要把你的代码放到框架合适的地方,框架会在合适的时机调用你的代码
- 框架规定了自己的编程方式,是一套完整的解决方案
- 使用框架的时候,由框架控制一切,我们只需要按照规则写代码
库和框架的区别
You
call Library, Framework
calls you
核心点:谁起到主导作用(控制反转)
控制整个流程的是框架
使用库,由开发人员决定如何调用库中提供的方法(辅助)
框架的侵入性很高(从头到尾)
2. 目前主流的前端框架
angular(前两三年非常火)
react(目前特别火的框架)—>国外使用较多
Vue(中国人自己写的框架
尤雨溪
) https://cn.vuejs.org/
Vue的版本:
2.x: 使用较多的版本
3.x: 还不太稳定的版本
3. MVVM的介绍
MVVM,一种更好的UI模式解决方案
4. MVC与MVVM
4.1 mvc
- M: Model 数据模型(专门用来操作数据,数据的CRUD)
- V:View 视图(对于前端来说,就是页面)
- C:Controller 控制器(是视图和数据模型沟通的桥梁,用于处理业务逻辑)
4.2 mvvm
- MVVM ===> M / V / VM
- M:model数据模型
- V:view视图
- VM:ViewModel 视图模型
4.3 优势对比
MVC模式,将应用程序划分为三大部分,实现了职责分离
在前端中经常要通过 JS代码 来进行一些逻辑操作,最终还要把这些逻辑操作的结果现在页面中。也就是需要频繁的操作DOM
MVVM通过数据双向绑定
- V(修改数据) —vm–> M
- M(修改数据)—vm–> V
- 数据是核心
Vue这种MVVM模式的框架,不推荐开发人员手动操作DOM
5 Vue中的MVVM
虽然没有完全遵循 MVVM 模型,Vue 的设计无疑受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的简称) 这个变量名表示 Vue 实例
学习Vue要转化思想
不要在想着怎么操作DOM,而是想着如何操作数据
!!!
1 | <div id="app">{{ msg }}</div> |
6. Vue实例
- 注意 1:先在data中声明数据,再使用数据
- 注意 2:可以通过
vm.$data
访问到data中的所有属性,或者vm.msg
1 | <script> |
7. 数据绑定
最常用的方式:Mustache(插值语法)
,也就是 {{}}
语法
解释:{{}}
从数据对象data
中获取数据
说明:数据对象的属性值发生了改变,插值处的内容都会更新
说明:{{}}
中只能出现JavaScript表达式(运算元+运算符) ,而不能解析js语句
注意:Mustache 语法不能作用在 HTML 元素的属性上
1 | <script> |
8. 双向数据绑定
双向数据绑定:将DOM与Vue实例的data数据绑定到一起,彼此之间相互影响
- 数据的改变会引起DOM的改变
- DOM的改变也会引起数据的变化
原理:
Object.defineProperty``get``set
getter
和setter
:访问器- 作用:指定
读取或设置
对象属性值的时候,执行的操作
参考地址
1
2
3
4
5
6
7
8
9
10<script>
/* defineProperty语法 介绍 */
var obj = {}
Object.defineProperty(obj, 'msg', {
// 设置 obj.msg = "1" 时set方法会被系统调用 参数分别是设置后和设置前的值
set: function (newVal, oldVal) { },
// 读取 obj.msg 时get方法会被系统调用
get: function ( newVal, oldVal ) {}
})
</script>
9. 自定义模拟数据绑定(数据代理)
1 | const obj = {} |
10. 动态添加数据的注意点
注意:只有
data
中的数据才是响应式的,动态添加进来的数据默认为非响应式可以通过以下方式实现动态添加数据的响应式
1
2Vue.set(object, key, value) - 适用于添加单个属性
Object.assign() - 适用于添加多个属性1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<script>
var vm = new Vue({
data: {
stu: {
name: 'jack',
age: 19
}
}
})
/* Vue.set */
Vue.set(vm.stu, 'gender', 'male')
/* Object.assign 将参数中的所有对象属性和值 合并到第一个参数 并返回合并后的对象*/
vm.stu = Object.assign({}, vm.stu, { gender: 'female', height: 180 })
</script>
11. 异步DOM更新
说明:Vue 异步执行 DOM 更新,监视所有数据改变,一次性更新DOM
优势:可以去除重复数据,对于避免不必要的计算和 避免重复 DOM 操作上,非常重要
如果需要拿到更新后dom中的数据 则需要通过
Vue.nextTick(callback)
- 实例调用
vm.$nextTick(function () {})
- 实例调用
1 | <script> |
11. vue指令
解释:指令 (Directives) 是带有
v-
前缀的特殊属性作用:当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM
11.1 v-text
解释:更新DOM对象的 textContent
1
<h1 v-text="msg"></h1>
11.2 v-html
- 解释:更新DOM对象的 innerHTML
1 | <h1 v-html="msg"></h1> |
11.3 v-bind
- 作用:当表达式的值改变时,将其产生的连带影响,作用于 DOM的属性
- 语法:
v-bind:title="msg"
- 简写:
:title="msg"
1 | <!-- 完整语法 --> |
11.4 v-model
- 作用:在表单元素上创建双向数据绑定
- 说明:监听用户的输入事件以更新数据
1 | <script> |
v-model修饰符
- number: 把绑定的值转换为
数值
类型; - trim: 把绑定的值去掉两边的空格;
- lazy: 为了优化效率问题,可以实现
懒绑定
,非实时的绑定(当焦点失去的时候,才把视图中的数据绑定在model上)
11.5 v-on
作用:绑定事件
语法:
1
2v-on:click="say" #直接不传递参数的绑定,默认或传递一个event参数
v-on:click="say('参数', $event)" #如果传递了参数,值不会自动传递event参数,如果需要则要手动传递 $event简写:
@click="say"
说明:绑定的事件定义在
methods
1
2
3
4<!-- 完整语法 -->
<a v-on:click="doSomething"></a>
<!-- 缩写 -->
<a @click="doSomething"></a>
事件修饰符
.stop
阻止冒泡,调用 event.stopPropagation()
.prevent
阻止默认行为,调用 event.preventDefault()
.capture
添加事件侦听器时使用事件捕获
模式
.self
只当事件在该元素本身(比如不是子元素)触发时,才会触发事件
.once
事件只触发一次
11.6 v-for
- 作用:基于源数据多次渲染元素或模板块
1 | <!-- 1 基础用法 --> |
key属性
推荐:使用
v-for
的时候提供key
属性,以获得性能提升。说明:使用 key,VUE会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
1
2
3<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
11.7 v-if 和 v-show
- 条件渲染
v-if
:根据表达式的值的真假条件,销毁或重建元素v-show
:根据表达式的真假值
,切换元素的 display CSS 属性
1 | <p v-show="isShow">这个元素展示出来了吗???</p> |
11.8 v-pre
- 说明:vue会跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
1 | <span v-pre>{{ this will not be compiled }}</span> |
11.9 v-once
- 说明:vue只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
1 | <span v-once>This will never change: {{msg}}</span> |
12. 样式处理 class和style
12.1 style的处理
1 | <div id="root"> |
12.2 class的处理
普通的class绑定(推荐使用)
1 | <style> |
绑定多个class
1 | <style> |
通过判断来进行class的绑定(推荐使用)
1 | <style> |
注意:无论是绑定style还是绑定class,都在原始的style或者class的基础上进行的样式叠加
,并不是替换原始的样式;
13. 过滤器
- 作用:文本数据格式化
- 过滤器可以用在两个地方:
{{}}
和 v-bind 表达式 - 两种过滤器:1 全局过滤器 2 局部过滤器
13.1 全局过滤器
- 说明:通过全局方式创建的过滤器,在任何一个vue实例中都可以使用
- 注意:使用全局过滤器的时候,需要先创建全局过滤器,再创建Vue实例
- 显示的内容,是由过滤器的返回值决定
- 使用语法:
<h1>{{name | myfilter1}}</h1>
1 | Vue.filter('filterName', function (value) { |
eg:
1 | <div id="app"> |
13.2 局部过滤器
- 说明:局部过滤器是在某一个vue实例的内容创建的,只在当前实例中起作用
1 | <div id="app"> |
14. 按键值修饰符
- 说明:在监听键盘事件时,Vue 允许为
v-on
在监听键盘事件时添加关键修饰符 - 键盘事件 - 键值修饰符
- 其他:修饰键(.ctrl等)、鼠标按键修饰符(.left等)
1 | <!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` --> |
15. 监听器watch
- 概述:
watch
是一个对象,键是需要观察的表达式,值是对应回调函数 - 作用:当表达式的值发生变化后,会调用对应的回调函数完成响应的监视操作
监听普通属性的改变:
1 | new Vue({ |
配置初始化监视:
1 | new Vue({ |
监视数组的改变:
1 | Vue.config.productionTip = false; |
监听对象的改变:
1 | new Vue({ |
1 | var vm = new Vue({ |
17. 实例(组件)生命周期
- 所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象即可 (一些根实例特有的选项除外)。
- 实例生命周期也叫做:组件生命周期
17.1 生命周期介绍
- 一个组件从开始到最后消亡所经历的各种状态,就是一个组件的生命周期
- 生命周期钩子函数的定义:从组件被创建,到组件挂载到页面上运行,再到页面关闭组件被卸载,这三个阶段总是伴随着组件各种各样的事件,这些事件,统称为组件的生命周期函数!
- 注意:Vue在执行过程中会自动调用
生命周期钩子函数
,我们只需要提供这些钩子函数即可 - 注意:钩子函数的名称都是Vue中规定好的
17.2 常用的钩子函数
17.2.1 钩子函数 - beforeCreate()
- 说明:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用
- 注意:此时,无法获取 data中的数据、methods中的方法
1 | var vue = new Vue({ |
17.2.2 钩子函数 - created()
- 注意:这是一个常用的生命周期,可以调用methods中的方法、改变data中的数据
- 使用场景:发送请求获取数据
17.2.3 钩子函数 - beforeMount()
- 说明:在挂载开始之前被调用
17.2.4 钩子函数 - mounted()
- 说明:此时,vue实例已经挂载到页面中,可以获取到el中的DOM元素,进行DOM操作
17.2.5 钩子函数 - beforeUpdate()
- 说明:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
- 注意:此处获取的数据是更新后的数据,但是获取页面中的DOM元素是更新之前的
17.2.6 钩子函数 - updated()
- 说明:组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。
17.2.7 钩子函数 - beforeDestroy()
- 说明:实例销毁之前调用。在这一步,实例仍然完全可用。
- 使用场景:实例销毁之前,执行清理任务,比如:清除定时器等
17.2.8 钩子函数 - destroyed()
- 说明:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
18 js中的promise
18.1 promise是什么
- 主要用于异步计算
- 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
- 可以在对象之间传递和操作promise,帮助我们处理队列
18.2 异步回调的问题
之前处理异步是通过纯粹的回调函数的形式进行处理
很容易进入到回调地狱中,剥夺了函数return的能力(异步调用如果return很有可能返回值为undefine)
问题可以解决,但是难以读懂,维护困难
稍有不慎就会踏入回调地狱 - 嵌套层次深,不好维护
一般情况我们一次性调用API就可以完成请求。有些情况需要多次调用服务器API,就会形成一个链式调用,比如为了完成一个功能,我们需要调用API1、API2、API3,依次按照顺序进行调用,这个时候就会出现回调地狱的问题
18.3 promise详解
promise是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)
并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据
代码风格,容易理解,便于维护
多个异步等待合并便于解决
1 | const a = 110; |
19. 网络请求axios
Promise based HTTP client for the browser and node.js
以Promise为基础的HTTP客户端,适用于:浏览器和node.js
封装ajax,用来发送请求,异步获取数据
安装:
npm i -S axios
cdn引入(如果项目简单就没必要使用脚手架)
1
2
3
4<!--axios vue中除了vue-resource官方的库的另外一个优秀的库-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!--qs(用来对象和请求字符串相互转换的库)-->
<script src="https://cdn.bootcss.com/qs/6.5.1/qs.min.js"></script>1
2
3
4
5
6
7
8//正在热映的电影
axios.get("https://douban.uieee.com/v2/movie/in_theaters")
.then((resp) => {
console.log(resp.data);
})
.catch(err => {
console.log(err);
})
19.1 发送get请求
完整写法:
1 | this.$myaxios({ |
简写:
1 | // url中带有query参数 |
19.2 发送post请求
完整写法:
1 | this.$myaxios({ |
简写
- 默认情况下,axios 会将JS对象序列化为JSON对象。为了使用
application/x-www-form-urlencoded
格式发送请求,我们可以这样:
1 | qs.stringify({ 'bar': 123 }) ===> "bar=123" |
19.3. 创建自定义的axios实例
默认使用axios实例,是由axios库提供的,我们可以基于axios库提供的实例进行增强,然后再使用;
1 | new Vue({ |
19.4 axios拦截器
拦截器会拦截发送的每一个请求,请求发送之前执行
request
中的函数,请求发送完成之后执行response
中的函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 请求拦截器
axios.interceptors.request.use(function (config) {
// 所有请求之前都要执行的操作
return config;
}, function (error) {
// 错误处理
return Promise.reject(error);
});
// 响应拦截器
axios.interceptors.response.use(function (response) {
// 所有请求完成后都要执行的操作
return response;
}, function (error) {
// 错误处理
return Promise.reject(error);
});
20. Vue自定义指令
20.1 全局自定义指令
1 | // 第一个参数:指令名称 |
20.2 局部自定义指令
1 | <div id="app"> |
21. Vue组件
组件: 完成局部特定功能的代码和资源的组合;
创建组件的两种方式:1 全局组件 2 局部组件
- 定义组件时,组件名称不能含有特殊字符,- 和 _也不能有
- 如果定义组件时,组件名称复杂建议使用大驼峰命名法
定义组件时如果使用的是驼峰命名法,那么使用时就要使用 -
分隔
21.1 全局组件
- 说明:全局组件在所有的vue实例中都可以使用(全局定义,全局有效)
- 注意:组件先得注册之后才能使用
1 | <div id="root"> |
21.2 局部组件
- 说明:局部组件,局部定义,局部有效
1 | <div id="root"> |
22. vue-cli脚手架的使用
- 安装nodejs
- 安装npm
1 | node -v |
- 配置淘宝镜像
1 | 查看当前镜像地址 |
- 安装vue-cli脚手架
1 | npm install @vue/cli -g |
- 使用脚手架创建vue商业项目
1 | 创建项目 |
23. 关闭eslint的语法检查
在项目的根目录创建vue项目的配置文件
vue-config.js
1
2
3
4module.exports = {
//关闭vue-cli中eslint的语法检查
lintOnSave: false
}
24. vue-cli添加对scss的支持
安装scss的loader加载器
1
2查看npm远程仓库中的全部版本号
npm show sass-loader versions1
2npm install sass-loader@7.3.1 --save-dev | -D
npm install node-sass@4.14.1 --save-dev | -D安装完成之后就可以使用scss的预编译器了
1
2
3
4
5
6
7
8
9
10<style scoped lang="scss">
#TodoHeader {
border: 2px solid red;
.box {
h1{
color: gray;
}
}
}
</style>
22. Vue的组件通信
22.1 父组件到子组件通信
方式:通过子组件
props
属性来传递数据 props是一个数组注意:属性的值必须在组件中通过
props
属性显示指定,否则,不会生效说明:传递过来的
props
属性的用法与data
属性的用法相同步骤:
- 父组件确定传字面量
my-sex="男"
还是父组件中的data属性:my-age="age"
- 在子组件中可以声明要接受的数据名称
props: ["mySex", "myAge"]
- 子组件的模板中即可使用父组件传递的数据了
- 父组件确定传字面量
1 | <template id="tp1"> |
22.2 子组件到父组件通信
父组件给子组件传递一个函数,由子组件调用这个函数
步骤:
在父组件中定义方法 parentFn
在子组件 组件引入标签 中绑定自定义事件 v-on:自定义事件名=”父组件中的方法” ==> @pfn=”parentFn”
子组件中通过
$emit()
触发自定义事件事件 this.$emit(pfn,参数列表。。。)
1 | <template id="tp1"> |
22.3 任意组件间的通信
- 全局事件总线
- 发布订阅(不常用)
- Vuex(状态管理)
23. Vue中的插槽slot
插槽的作用: 让父组件可以向子组件的指定位置插入html结构,其实也是变相的实现了组件通信 父-->子
插槽的分类: 默认插槽 具名插槽 作用域插槽
给插槽传递的html结构尽量使用 <template> 包含在里面
23.1 默认插槽(匿名插槽)
1 | <template> |
1 | <template> |
23.2 具名插槽
1 | <template> |
1 | <template> |
23.3 作用域插槽
作用域插槽是: 插槽的使用者传递结构,而插槽中的数据却在slot的定义的组件中;
1 | <template> |
1 | <!--父组件中使用作用域插槽 --> |
24. Vue中的路由
24.1 路由的基本使用
Spa页面应用理解:
- 单页web应用(single page web application,spa)
- 整个应用只有一个完整的页面
index.html
- 点击页面中的导航链接,不会刷新页面,只会做页面的局部更新
- 数据需要通过ajax获取
前端路由的理解:
- 一个路由就是一组映射关系(key—value)
- key为路径,value是component 用于展示页面内容
- 当浏览器路径改变时,对应的组件就会显示
安装vue-router插件:
npm install vue-router --save
|npm install vue-router
在
src
目录中创建一个目录router
,在router中新建一个文件index.js
路由组件在使用的时候不需要注册,只需要在路由器中配置即可
src/router/index.js
1 | import Home from "@/pages/Home" |
在main.js中引入编写的路由器:
1 | import Vue from 'vue' |
在App组件中编写
路由链接
及其路由容器
:
1 | <template> |
24.2 多级(嵌套)路由
注册路由 src/router/index.js
1 | import Home from "@/pages/Home" |
编写About.vue
1 | <template> |
24.3 路由的重定向
1 | { |
24.4 路由的query参数获取
在About组件中编写路由链接:
About.vue
1 | <router-link class="nav" to="/about/about1?id=10&name=admin" active-class="active">关于我们1</router-link> |
在About1中获取参数
About1.vue
1 | <script> |
24.5 命名路由
1 | export default new VueRouter({ |
24.6 路由的params参数(RustFul风格)
params参数其实就是RestFul风格的一种路由;
注册路由
@/router/index.js
1 | { |
在About组件中进行跳转
1 | <router-link class="nav" to="/about/about1/10/admin123" active-class="active">关于我们1</router-link> |
在About1组件中进行接收
1 | <script> |
24.7 路由的跳转模式
默认router-link
路由的跳转的方式为push,会不断的追加到浏览器的历史记录中;
我们可以使用replace方式直接进行替换,而不是push追加;
配置路由的跳转方式为
replace
1 | <router-link replace class="nav" to="/home" active-class="active">首页Home</router-link> |
24.8 编程式路由导航
1 | <template> |
24.9 路由的两种工作模式(Hash|History)
Hash模式: #及其#之后的内容并不会发送给服务器
History模式:mode:"history"
24.10 全局路由守卫
全局路由守卫分为 全局前置路由守卫
和 全局后置路由首位
着重了解 全局前置路由守卫
1 | //全局前置路由守卫 |
24.11 动态添加路由
1 | router.addRoute( |
注意: 无论是静态路由还是动态添加路由,children
中的path
配置项都不能加 /
;
25. 前端的模块化
25.1 为什么需要模块化?
- 最开始的js就是为了实现客户端验证以及一些简单的效果
- 后来,js得到重视,应用越来越广泛,前端开发的复杂度越来越高
- 旧版本的js中没有提供与模块(module)相关的内容
25.2 模块的概念
- 在js中,一个模块就是实现特定功能的文件(js文件)
- 遵循模块的机制,想要什么功能就加载什么模块
- 模块化开发需要遵循规范
25.3 模块化解决的问题
- 命名冲突
- 文件依赖(加载文件)
- 模块的复用
- 统一规范和开发方式
25.4 模块化的历史
在Es6之前,javascript没有模块系统,它无法将一个大程序拆分成若干个互相依赖的小文件,然后在用简单的方法拼装起来.为了做到模块化,在Es6之前,引入了AMD(Asynchronous module definition)与CMD(common module definition)
前者典型代表是requireJS(外国人搞出来的),后者是seajs(国内阿里大神)
共同点:都是对模块定义的不同规范,都是异步加载模块,并且解决文件之间的依赖重命名冲突等问题。
不同点:模块定义的方式和模块加载机制是不同的,前者AMD(requirejs)是将所有文件同时加载,一次性引入,推崇依赖前置,也就是在定义模块时要先声明其依赖的模块,加载完模块后会立马执行该模块(运行时加载)
而CMD(seajs)强调的是一个文件一个模块,可按需引入,推崇依赖就近,加载完某个模块后不会立即执行,而是等遇到了require语句的时候在执行
两者的使用加载机制不同,也就导致了AMD(requirejs)模块会提前执行,用户体验好,而CMD(seajs)性能好,因为只有在需要时候才执行,在服务器端,nodejs使用的就是cmd规范,也就是需要什么包,就引入什么包,按需加入(编译时加载)
而在Es6的语言规格中引入了模块化功能,也就很好的取代了之前的commonjs和AMD规范了,成为了浏览器和服务器的通用的模块解决方案,在现今(vuejs,ReactJS)等框架大行其道中,都引入了Es6中的模块化(Module)机制,一些自动化打包工具webpack或者微信小游戏中也同样如此
26 Webpack
26.1 webpack概述
webpack解决了现存模块打包器的两个痛点
- Code Spliting - 代码分离 按需加载
- 静态资源的模块化处理方案
webpack 是一个现代 JavaScript 应用程序的模块打包器(特点 module、 bundler)
webpack 是一个模块化方案(预编译)
webpack获取具有依赖关系的模块,并生成表示这些模块的静态资源
四个核心概念:入口(entry)、输出(output)、加载器loader、插件(plugins)
webpack 和 requirejs对比
1
2webpack 预编译 (在开发阶段通过webpack进行模块化处理, 最终项目上线, 就不在依赖于 webpack)
requirejs 线上的编译( 代码运行是需要依赖与 requirejs 的 )
26.2 webpack与模块
- 在webpack看来:所有的静态资源都是模块
- webpack 模块能够识别以下等形式的模块之间的依赖
26.3 webpack打包
vue-cli集成了webpack,我们可以不用去了解webpack复杂的打包过程
1 | vue init webpack pro01 //使用vue-cli脚手架+webpack打包工具构建项目 |
27. Es6中的export
export default 向外暴露的成员,可以使用任意的变量来接收
在一个模块中,export default只允许向外暴露一次
在一个模块中,可以同时使用export default 和 export向外暴露成员
1 | //test.vue |
1 | //mian.vue |
1 | 打印结果: |
- 使用export向外暴露成员,只能用{}的形式来接收,这种形式,叫做【按需导出】
- export可以向外暴露多个成员,同时,如果某些成员,我们在import的时候不需要,则可以不在{}中定义
- 使用export导出的成员必须严格按照导出时候的名称,来使用{}按需接收;
- 如果使用export按需导出的成员想换名称,可以用as进行替换
28. Vue中的全局事件总线
在Vue开发中会遇到大量的组件之间共享数据的情形,针对不同的情形,Vue有相对应的解决方案。比如,父组件向子组件传值可以使用props
,复杂项目中不同模块之间传值可以使用Vuex
。
但是,对于一些简单的项目里的非父子组件来说,它们一方面不适用props,另一方面又没有必要使用Vuex,针对这种情形可以使用中央事件总线(Event Bus)来解决问题。
1 | const vm = new Vue({ |
在组件TodoItem中发送数据(触发事件)
1 | export default { |
然后就可以在组件App中接收了
1 | methods: { |
29. 浏览器中的数据存储技术
cookie
浏览器端的数据存储技术,以文本的形式存放,可以设置有效时间
1
document.cookie = "myname=admin"
sessionStorage
只在本次会话中有效,浏览器关闭(新开标签页)就会失效;
1
2
3
4
5
6if (sessionStorage.getItem("myname")) {
console.log("获取到sessionStorage中的数据:" + sessionStorage.getItem("myname"))
} else {
console.log("开始给sessionStorage添加数据")
sessionStorage.setItem("myname", "admin")
}localStorage
只要不是手动清除,永久有效
1
2
3
4
5
6if (localStorage.getItem("myname")) {
console.log("获取到localStorage中的数据:" + localStorage.getItem("myname"))
} else {
console.log("开始给localStorage添加数据")
localStorage.setItem("myname", "admin")
}
30. Vuex状态管理
30.1 什么是Vuex?
专门在Vue中实现集中式状态(数据)管理的插件,对Vue中多个组件共享状态(数据)进行集中式管理(读/写),也是一种组件的通信方式,且适用于任何组件之间进行通信;
30.2 什么时候使用Vuex?
- 多个组件依赖同一个状态
- 来自不同组件的行为需要
变更同一状态
30.3 Vuex的工作流程
VueComponent
—->(dispatch)—->Actions
—->(commit)—>Mutations
–(mutate)–>State
–(render)–>VueComponent
- 组件Vue Component通过dispatch来调用actions提供的方法
- 而actions除了可以和api打交道外,还可以通过commit来调mutations提供的方法
- 最后mutaions将数据保存到state中
- 当然,Vue Components还以通过getters提供的方法获取state中的数据
- state (类似存储全局变量的数据)
- getters (提供用来获取state数据的方法)
- actions (提供跟后台接口打交道的方法,并调用mutations提供的方法)
- mutations (提供存储设置state数据的方法)
30.4 Vuex的初级使用
1 | npm install vuex --save //安装vuex |
main.js
1 | import Vuex from "vuex"; |
组件中访问共享状态:
1 | store.state.a; //访问共享数据(不建议这种方式) |
30.5 Vuex的商业使用规范
在src
目录中创建store
目录,在store
目录中再创建index.js
index.js
1 | import Vue from "vue"; |
组件中就可以使用一下方式改变store中存储的共享状态(数据)了:
1 | //通过调用action动作修改 |
30.6 getters配置项的使用
getters配置项就是给state中的数据进行加工用的:
1 | getters: { |
在组件中进行使用:
1 | {{ $store.getters.bigA }} |
31. devDependencies与dependencies
- devDependencies用于本地环境开发时候。
npm install xxx --save-dev
- dependencies用户发布环境(生产环境)
npm install xxx --save
- devDependencies是只会在开发环境下依赖的模块,生产环境不会被打入包内。
- 而dependencies依赖的包不仅开发环境能使用,生产环境也能使用。其实这句话是重点,按照这个观念很容易决定安装模块时是使用
--save
还是--save-dev
- ~表示末尾最大,^表示中间最大,*****表示第一个最大
32. Vue中的UI组件库
32.1 移动端UI组件库
Vant
Cube UI
Mint UI
32.2 PC端UI组件库
- Element-ui
- IView-ui