1.1 简介
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式的js框架,发布于 2014 年 2 月。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库(如:vue-router,vue-resource,vuex)或既有项目整合。
1.2 MVVM 模式的实现者——双向数据绑定模式
Model:模型层,在这里表示 JavaScript 对象
View:视图层,在这里表示 DOM(HTML 操作的元素)
ViewModel:连接视图和数据的中间件,Vue.js 就是 MVVM 中的 ViewModel 层的实现者
在 MVVM 架构中,是不允许 数据 和 视图 直接通信的,只能通过 ViewModel 来通信,而 ViewModel 就是定义了一个Observer` 观察者
ViewModel 能够观察到数据的变化,并对视图下对应的内容进行更新
ViewModel 能够监听到视图的变化,并能够通知数据发生改变
至此,我们就明白了,Vue.js 就是一个 MVVM 的实现者,他的核心就是实现了 DOM 监听 与 数据绑定
1.3 其它 MVVM 实现者
AngularJS
简单介绍一下,AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购。是一款优秀的前端JS框架,已经被用于Google的多款产品当中。AngularJS有着诸多特性,最为核心的是:MVVM、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。
ReactJS
React引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。
微信小程序
微信小程序的视图层和数据层就是通过MVVM进行绑定的。
1.4 为什么要使用 Vue.js
轻量级,体积小是一个重要指标。Vue.js 压缩后有只有 20多kb (Angular 压缩后 56kb+,React 压缩后 44kb+)
移动优先。更适合移动端,比如移动端的 Touch 事件
易上手,学习曲线平稳,文档齐全
吸取了 Angular(模块化)和 React(虚拟 DOM)的长处,并拥有自己独特的功能,如:计算属性
开源,社区活跃度高
1.5 Vue.js 的两大核心要素
1.5.1 数据驱动
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是 ES5 中一个特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。这里需要注意的问题是浏览器控制台在打印数据对象时 getter/setter 的格式化并不同,所以你可能需要安装 vue-devtools 来获取更加友好的检查接口。
每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
1.5.2 组件化
页面上每个独立的可交互的区域视为一个组件
每个组件对应一个工程目录,组件所需的各种资源在这个目录下就近维护
页面不过是组件的容器,组件可以嵌套自由组合(复用)形成完整的页面
2.1在页面引入vue的js文件即可,忘了拷贝官网的,否则百度bootcdn这个网站找也行
cdn是一种加速策略,能够快速访问js文件,但是如果网站不行,也可以用资料的vue.js拖到html文件引入即可!!!
2.2 在页面中绑定vue元素
创建一个div,id是app
2.3 创建vue对象,设计对象的内容
其中该vue对象,绑定了页面中id是app的那个div
# el: element的简称,也就是Vue实例挂载的元素节点,值可以是 CSS 选择符,或实际 HTML 元素,或返回 HTML 元素的函数。 # data: 用于提供数据的对象,里面存放键值对数据。
2.4 在页面的元素中使用插值表达式来使用vue对象中的内容
{{title}}
插值表达式的作用是在View中获得Model中的内容
Model中的内容如下:
new Vue({
el:"#app",
data:{
title:"hello world!"
},
methods:{
sayHello:function(){
return "hello vue";
}
}
});
3.1 简单使用插值表达式获取数据
{{title}}
此时,页面上将会显示"Hello world!"
3.2 在插值表达式中获取数组中的内容
{{[1,2,3,4][2]}}
此时,页面上会显示“3”,也就是数组中的第三个元素被获取。
3.3 使用插值表达式获取对象中的属性
{{ {"name":"xiaoyu","age":20}.age }}
此时,页面上会显示“20”,也就是对象中age属性的值。
3.4 使用插值表达式调用Vue中的方法
{{ sayHello()}}
此时,页面上会显示“hello vue”,也就是调用了vue对象中的sayHello方法,并展示了方法的返回值。
3.5 插值表达式总结↓
Title
{{msg}}
{{[1,2,3][0]}}
{{{name:"fbb",age:18}.name}}
{{hello()}}
{{1+2}}
{{1>0?666:777}}
Vue.js通过加载js,实现对页面的快速渲染,vue封装的js该如何使用?就必须了解MVVM双向数据绑定模式,Vue将视图层和数据层分离,通过MVVM建立视图层和数据层的连接,其中,插值表达式是一种连接方式,可以通过插值表达式以多种方式,快速的从数据层获取数据并展示在视图层上,数据层Vue对象,也是由很多部分组成,
5.1 v-if
Vue中的分支语句v-if非常好理解,逻辑跟Java中的if-else相同。v-if语句块包含以下内容:
v-if
v-else
v-else-if
接下来以一个简单例子即可理解:
今天天气很舒服!
今天天气很燥热!晚上要去放松一下!
晚上只能自嗨!
从这个例子可以看出,vue对象中的data提供了分支的条件。根据条件,如果是true,则v-if的内容就会显示,反之不显示。
5.2 v-show
v-if和v-show之间有着看似相同的效果,但优化上却有区别。先看下面这个例子:
有钱!
有钱!
通过点击“今晚彩票开奖”按钮,能切换rich的值,此时发现,v-if和v-show的显示状态都会来回切换。看起来是一样的,但通过查看控制台代码发现,v-show实际会将p标签的css样式的display属性设为none来达到隐藏的效果。
而v-if是直接在页面上添加和删除p标签来达到效果,因此v-show在反复切换的应用场景下,效率比v-if更高。
5.3 总结:v-if是增删元素节点来实现,而v-show只是修改样式display的值来达到显示和隐藏,如果不断切换显示隐藏推荐用v-show,效率更高↓
Vue中的循环关键字并没有Java的那么多,只有v-for,但用法上有多种,接下来我们来逐一介绍
6.1 普通的for循环,遍历数组
我们需要定义数组作为数据源,然后通过v-for来遍历数据源,再使用差值表达式输出数据
- {{a}}
在这个例子中,数据源提供了一个数组,视图层通过v-for来循环输出多个li标签,非常简单
6.2 带着索引的for,遍历数组,多了()这个整体来指定元素和索引而已,跟上面语法基本一致↑↓
- {{i}}{{a}}
此时的i就是每次循环的循环变量(索引) ,从0开始一直到元素个数-1
6.3 遍历一个对象中的信息: v、k、i,其实这里的对象理解为map结构即可,map也是对象↓
- {{i+1}}--{{k}}--{{v}}
v、k、i 这几个字符可以自己定义,分别表示每次循环内容的值、键、序号。
v: 循环中每条数据的值 小鱼、20、如花
k: 循环中每天数据的键 username、age、girl
i: 循环的序号,从0开始
页面效果如下: |
---|
![]() |
6.4 遍历一个对象数组(搞一个数组装学生对象):for循环的嵌套,遍历数组里面包含对象
-
{{i+1}}--{{k}}--{{v}}
可以清楚的看到,此时数据源是一个student数组,通过两层v-for循环,外层遍历数组中的每个student对象,内层v-for遍历每个对象的v、k、i。
页面效果如下:
6.5 v-for总结,无非是遍历一个数组,遍历一个对象,遍历一个数组里面包含的对象,总体代码和运行结果如下↓
Title
{{i}}{{e}}
{{student.name}}
{{student.age}}
{{i}}
{{k}}
{{v}}
{{student.name}}
{{student.age}}
{{i}}
{{k}}
{{v}}
Vue提供了多个关键字,能快速的将数据对象中的值,绑定在视图中
7.1 v-model,巧记,v代表value值,model代表data,将value值和data双向绑定,数据联动↓
通过v-model将标签的value值与vue对象中的data属性值进行绑定
Title
{{msg}}
此时input标签中加入了属性v-model="msg",表示input的value值与vue里面的data对象中的msg属性绑定,
当在input输入框中输入内容,会实时修改msg的值,于是{{msg}}插值表达式,能实时输出input输入框内的值
7.2 v-bind:绑定某个标签属性,可以理解为v-mode其实是v-model:value,那么v-bind:属性
我们知道插值表达式是不能写在html的标签的属性内的,那如果一定要用vue中的属性作为html标签的属性的内容,就可以通过v-bind:进行属性绑定
这样,a标签内的href属性就可以使用vue对象中的属性值
注意, v-bind也可以简写,使用冒号“:”来代替,巧记,不是骂人哈,傻b,傻冒,v-bind后有冒号:,:理解为绑定,对应
==>
7.3 总结,既然v-model和v-bind:都能绑定data中的属性,那为啥还要v-model,因为v-model是双向绑定,而v-bind:是单向绑定,代码和运行效果如下↓
Title
{{msg}}
点我跳转到百度
8.1 v-on:事件,或者用@事件都行↓
通过配合具体的事件名,来绑定vue中定义的函数
Title
new Vue({
el:"#app",
data: {
msg: "hello",
url:"http://www.baidu.com"
},
methods:{
add:function () {
alert("按钮被点击啦")
}
}
});
8.2 事件修饰符,直接去官方文档的搜索框,输入事件修饰符,即可查看对应内容,来了解一下↓
可以使用Vue中定义好的事件修饰符,快速达到效果,查看以下例子了解一下,这里举个例子,其他有兴趣查看官网
x:{{x}}
y:{{y}}
鼠标移动到此即停止
当鼠标经过P标签区域内时,区域内就会显示X和Y轴的坐标,如果经过P标签内的Span标签内时,此时会调用事件属性mousemove.stop预定的效果,鼠标移动的效果将会被取消,X和Y不再显示信息
8.3计算属性,computed↓
8.3.1 什么是计算属性
计算属性,重点突出在属性两个字上(属性是名词),首先它是个 属性,其次这个属性有计算的能力(计算是动词),
这里的计算就是个函数,简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性)
8.3.2 计算属性与方法的区别,拷贝下面例子来了解一下↓
布局篇 计算属性
调用当前时间的方法:{{currentTime1()}}
当前时间的计算属性:{{currentTime2}}
说明
methods:定义方法,插值表达式调用方法,使用 currentTime1(),需要带括号
computed:定义计算属性,插值表达式调用属性,使用 currentTime2,不需要带括号,this.message 是为了能够观察到修改了currentTime2的数据进行了更新,而不再使用旧的缓存数据,进行缓存更新,看数据的变化↓
注意:methods和computed里不能重名!
8.3.3 测试效果
8.3.4 总结,计算属性有缓存效果,只有计算属性里面的数据发生改变时,才会更新缓存重新计算,而方法每次都计算↓
调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?
此时就可以考虑将这个结果缓存起来,而采用计算属性可以很方便的做到这一点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销,打开控制台,然后vm选择方法或者属性测试即可↓
9.1 什么是“组件化”
可以理解为Vue的组件化设计思想,借鉴了Java的面向对象思想,Java认为万物皆对象,在Vue中万物皆组件
在实际的vue项目中,以及使用了Vue框架的项目中,Vue的对象都会以组件的形式出现,能被反复使用
而要想实现组件化,需要在页面中,进行注册组件,关于注册的方式有两种,分别是全局注册和本地(局部)注册↓
9.1.1 组件的全局注册
vue组件的全局注册
9.1.2 组件的本地注册
vue的全局注册,也就意味着在页面的任意一个被vue绑定过的div中,都可以使用全局注册了的vue组件
但是,如果是对vue组件进行本地注册,那么在其他被vue绑定的div中,不能使用该组件
vue组件的本地(局部)注册
9.1.3 小结
这是一个完整的Vue组件,该组件包含了三个部分,template(html视图层内容),script(Model层),style(CSS样式),这样封装好的组件可以被复用,也可以作为其他组件的组成部分而被封装——Java的面向对象再次体现
特点1,template标签内,必须有且只能有一个根标签
特点2,componet中注册的组件中的data,必须是函数的形式,如下↓
data:function(){
return {
title:"hello vue"
}
}
9.2 组件的生命周期
Vue中的组件也是有生命周期的,一个Vue组件会经历:初始化,创建,绑定,更新,销毁等阶段,不同的阶段,都会有相应的生命周期钩子函数被调用
生命周期
{{title}}
组件的生命周期钩子,创建,挂载,更新,销毁,都有前后 |
---|
![]() |
10.1 什么是vue-cli
cli: Command Line 命令行工具,vue-cli就是vue的命令行工具,也称之为脚手架,使用vue-cli提供的各种命令可以拉取,创建,运行我们需要使用到的骨架,比如webpack,Element UI,Element Admin等等,但是,要想使用vue-cli命令,需要先安装node.js
10.2 node.js的介绍及安装
node.js的介绍
node.js提供了前端程序的运行环境,可以把node.js理解成是运行前端程序的服务器
node.js的安装
从官网下载安装即可: 下载 | Node.js 中文网
win7提示安装不了高版本,可以用低版本来,下载地址Index of /dist/v12.16.2/
下载完成得到安装文件双击下一步安装即可
测试node.js是否安装成功,在DOS窗口中输入“node -v” 查看版本,如果看到版本,就表示安装成功↓ |
---|
![]() |
10.3 使用node.js安装vue-cli脚手架
命令行黑窗体cmd中,使用如下命令安装vue-cli
npm install vue-cli -g
npm,使用node.js的命令
install,安装
vue-cli,要安装的vue-cli
-g,全局安装
当出现以下界面,表示正在安装: |
---|
![]() |
另外,如果使用npm官方镜像速度比较慢,推荐使用淘宝镜像来安装↓
npm install -g cnpm --registry=https://registry.npm.taobao.org
之后,使用npm命令时,可以替换成用cnpm命令来操作↓
cnpm install vue-cli -g
#下面是等会项目中需要用到的命令,这里安装vue-cli脚手架,只需要安装这个cnpm install vue-cli -g命令即可 cnpm install cnpm run dev
10.4 使用vue-cli下载项目骨架,来搭建我们的项目
就像maven一样,vue为我们提供了一些官方项目骨架,使用vue list命令可以列出当前官方提供的骨架,比如下面的webpack,可以使用这些骨架,来快速搭建出项目
vue list
10.5 创建项目目录并打开↓
win r输入cmd打开默认路径是用户名所在路径,切换到e盘之前,在e盘创建好my-vue-project,然
mkdir e:/my-vue-project cd e:/my-vue-project
10.6 使用Webpack骨架快速创建项目
在my-vue-project目录中使用以下命令下载项目骨架
vue init webpack my-project1
webpack: 骨架名称
my-project1: 项目名称
过程中会出现如下界面,需要手动操作,暂时先选No,然后按照提示下一步操作即可,简单↓ |
---|
![]() |
出现如下界面,表示安装成功 |
---|
![]() |
按照上面提示,进入到my-project1文件夹内后,使用以下命令来运行项目↓
cd my-project1
npm run dev
运行完上面的命令后,就会得到下面访问项目的地址↓
浏览器访问这个地址http://localhost:8080/就可以看到我们创建好的vue项目啦,如下图所示↓
访问http://localhost:8080,页面效果如下↓ |
---|
![]() |
使用webpack骨架创建好的vue项目的结构如下,先了解一下即可↓
用idea关闭其他项目,然后直接open找到要打开的项目路径,此时,项目目录及各目录介绍如下↓ |
---|
![]() |
10.7 webpack项目的几个常用命令介绍
npm install
在运行和调试项目前,一般都需要先执行该命令,目的是安装项目运行所需要的环境
npm run dev
以调试的方式运行项目
npm run build
生成用于项目部署所需的最小资源,生成的内容存放在build文件夹内
11.1 idea中安装vue插件来操作.vue文件
在idea中下载vue插件然后后提示重启idea,
第二步,重启后在idea中配置,让idea能够操作.vue文件,下图中点击绿色+号后,输入框中输入的内容是*.vue
这样的好处是,鼠标右键就可以创建.vue文件,即vue组件了↓
11.2 组件的参数传递,首先在项目中创建子组件↓
创建子组件Content组件
商品列表...
{{MyTitle}}
11.3 main.js中配置注册子组件
在main.js中注册子组件
import Vue from 'vue';
import App from './App.vue';
import Content from './components/Content';//引入Content
Vue.component('MyContent',Content);//全局注册组件,组件起个名字MyContent,方便在其他页面,标签引用↓
new Vue({
el: '#app',
render: h => h(App)
})
11.4 在App.vue中使用子组件并传递参数,这个案例同时涉及到了父传子和子传父↓
拷贝上面代码测试即可,简单,下面是父传子和子传父是详细的流程说明而已↓
http://localhost:8080/#/↓
http://localhost:8080/#/↓
11.5 父传子
通过子组件的props部分,来指明可以接收的参数,父组件通过在标签中写明参数的键值对来传递参数
props是表示一个组件的参数部分,并且props的写法有两种↓
1)props:{参数名1:{type:String,required:true,default:'XX'},参数名2:{...}}
2)props:[参数列表]比如props:['MyProp1','MyProp2',...]
11.6 子传父
关于子传父的过程,下图已经是详细步骤说明,其实一点也不复杂,主要看下图粉红色线演示的是子传父的过程↓
1上面的父传子和子传入,测试流程图解说明↓
2如何在App.vue中使用子组件↓
12.1 安装路由模块
npm install vue-router -s
12.2 引入路由模块并使用
在main.js中引入路由模块并使用
import Vue from 'vue'
import App from './App'
import router from './router' //引入路由模块
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router, //使用路由模块
components: { App },
template: ' '
})
注意,如果是创建一个新的项目,选择路由的时候选y表示yes,那么上面两步在创建好的项目中就已经写好了↑
12.3 路由初体验↓
12.3.1 创建App.vue
改变url,发现
中的内容发生改变
http://localhost:8080/#/ 显示home
http://localhost:8080/#/user 显示user
向router实例中添加mode属性:
值"hash": url带# 适用于调试模式
值"history" url不带#
12.3.2 创建Home.vue
首页
12.3.3 创建Product.vue
商品列表 商品的id:{{id}}
12.3.4 修改静态路由表
修改路由表src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Home from "../components/Home";
import Product from "../components/Product";
Vue.use(Router)
export default new Router({
routes: [
{
path:'/Home',
component: Home
},
{
path:'/Product/:id', //设参
component:Product
}
]
})
12.4 参数传递
在路由表中设参/:id
export default new Router({
routes: [
...
{
path:'/Product/:id', //设参
component:Product
}
]
})
在App.vue中传参/1
在Product.vue中接参,通过this里面的内置路由对象没有r的参数对象的id来获取,存储到数据data中↓
商品列表 商品的id:{{id}}
12.5 程序式路由的实现,比如点击按钮,通过this里面内置的路由器对象r的推送方法来实现↓
使用
进行路由跳转是有局限性的,也可以通过this.$router.push('/Product/1')的js方式实现路由跳转更加灵活↓
13.1 什么是 Axios
Axios是一个开源的,可以用在浏览器端和NodeJS的异步通信框架,她的主要作用就是实现AJAX 异步通信,其功能特点如下:
从浏览器中创建XMLHttpRequests
从node.js创建http 请求
支持Promise API
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换JSON 数据
客户端支持防御XSRF(跨站请求伪造)
GitHub:GitHub - axios/axios: Promise based HTTP client for the browser and node.js
13.2 为什么要使用 Axios
由于Vue.js是一个视图层框架,并且作者(尤雨溪),严格准守SoC(关注度分离原则),所以Vue.js并不包含AJAX的通信功能,为了解决通信问题,作者单独开发了一个名为vue-resource的插件,不过在进入2.0 版本以后停止了对该插件的维护,并推荐了Axios框架
13.3 Axios的使用↓
13.3.1 安装vue axios
npm install --save axios vue-axios
13.3.2 在main.js中引入vue axios
在项目中使用axios模块
import Vue from 'vue';
import axios from 'axios';//引入
import VueAxios from 'vue-axios';///引入
Vue.use(VueAxios, axios);//引入
13.3.3 发送ajax请求
Regist
Email
{{mail}}
Password
{{password}}
Gender
男
女
Hobby
音乐
电影
运动
13.3.4 服务端mvc跨域配置,解决跨域问题↓
在spring-mvc.xml中加入上述这一段,其中,allowed-origins指的是允许的访问源的域名,"*"表示任何人都可以访问,也可以指明具体的域名
13.3.5 解决axios无法传递data中的参数问题↓
原因,默认情况下发送axios时请求头中的内容类型为下面,但是后端没有使用@RequestBody↓
Content-Type:application/json;charset=UTF-8
而实际服务端需要的是下面↓
Content-Type:application/x-www-form-urlencoded
因此,使用axios的qs内置库中的方法进行内容类型的转换,在App.vue里面进行下面配置,使用即可↓
import Qs from 'qs'
this.axios({
method:'post',
url:'http://localhost:8081/regist',
transformRequest: [function (data) {
return Qs.stringify(data)
}],
data:{
email:this.email
}
})
.then(function (response) {
alert(response.data.message)
});
对项目进行中的内容进行调整,结构如下: |
---|
![]() |
各部分内容↓
14.1 router路由模块:index.js(路由配置表)↓
import Vue from 'vue'
import Router from 'vue-router'
import Login from '../views/Login'
import Home from '../views/Home'
// 安装路由
Vue.use(Router);
// 配置路由
export default new Router({
routes: [
{
// 路由路径
path: '/Login',
// 路由名称
name: 'Login',
// 跳转到组件
component: Login
},
{
path:'/Home',
name:'Home',
component:Home
}
]
});
14.2 使用Element-UI组件库,下面的安装和引入忘了的话去官网抄即可,一样的↓
14.2.1 安装Element-UI
ctr c停止在idea中的项目,然后在项目文件夹内使用命令来安装element-ui模块
npm i element-ui -S
14.2.2 在main.js中引入Element-UI
在vue项目中引入element-ui并使用,在main.js中写入以下内容↓
import Vue from 'vue';
import ElementUI from 'element-ui'; //引入
import 'element-ui/lib/theme-chalk/index.css';//引入
import App from './App.vue';
Vue.use(ElementUI);//引入
new Vue({
el: '#app',
render: h => h(App)//引入
});
上面修改完后,进入项目文件夹,用npm run dev重新运行我们的项目,因为上面ctr c停止了项目
14.2.3 在Element-UI组件库中查找组件↓
在官方组件库中,根据需求找到组件,然后在项目中使用 |
---|
![]() |
14.3 编写登录组件Login.vue
欢迎登录
登录
输入的用户名和密码,通过Axios请求去后端做校验,若校验成功则路由至Home组件
登录页面的展示效果:(Element UI),这个效果其实直接拷贝官网表单验证,加上上面的style即css样式即可↓ |
---|
![]() |
14.4 编写入口js即main.js
import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
// 导入上面创建的路由配置表
import router from './router'
// 导入ElementUI模块
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueRouter);
// 使用ElementUI模块
Vue.use(ElementUI);
// 使用Axios (vue中实现ajax功能的组件)
Vue.use(VueAxios, axios)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
// 配置路由
router,
render: h => h(App)
})
15.1 什么是Vuex
Vuex是一个专为Vue.js应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则,保证状态以一种可预测的方式发生变化
15.2 安装和引入Vuex
在项目根目录执行如下命令来安装 Vuex
若失败,可使用cnpm
下面这样是安装最新版,最新版对应的vue可能不是你安装的版本 npm install vuex --save 所以推荐用下面的方式来指定版本来安装,来对应我们之前的vue2.0版本,用下面这个安装即可↓ npm install [email protected] --save
修改
main.js
文件,导入Vuex,关键代码如下↓
import Vuex from 'vuex';//引入
Vue.use(Vuex);//引入
15.3 配置vuex↓
15.3.1 创建Vuex 配置文件
在src目录下,创建一个名为store的目录,并新建一个名为index.js文件,用来配置Vuex,代码如下,拷贝即可↓
i
mport Vue from 'vue'
import Vuex from 'vuex'//引入
Vue.use(Vuex);//引入
// 全局state对象,用于保存所有组件的公共数据
const state = {
// 定义一个user对象,理解未定义了一个状态对象
// 在组件中是通过this.$store.state.user来获取
user: {
name: ''
}
};
// 实时监听state值的最新状态,注意这里的getters可以理解为计算属性
const getters = {
// 在组件中是通过this.$store.getters.getUser来获取
getUser(state) {//理解为状态对象的getter方法
return state.user;
}
};
// 定义改变state初始值的方法,这里是唯一可以改变state的地方,缺点是只能同步执行修改
const mutations = {
// 在组件中是通过this.$store.commit('updateUser', user);方法来调用mutations
updateUser(state, user) {//理解为状态对象的setter方法
state.user = user;
}
};
// 定义触发mutations里函数的方法,可以异步执行mutations里的函数
const actions = {
// 在组件中是通过this.$store.dispatch('asyncUpdateUser', user);来调用actions
asyncUpdateUser(context, user) {//理解为状态对象的setter方法,吃软饭的↓
context.commit('updateUser', user);//还是调用上面的同步修改方法updateUser,本身多了异步的效果而已↑
}
};
export default new Vuex.Store({
state,
getters,
mutations,
actions
});
修改main.js,增加刚才配置的store/index.js,关键代码如下↓
import Vue from 'vue'
import Vuex from 'vuex'
import store from './store';//引入
Vue.use(Vuex);
new Vue({
el: '#app',
store,//引入
});
15.3.2 解决浏览器刷新后Vuex数据消失问题↓
问题描述
Vuex的状态存储是响应式的,当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会相应地得到高效更新,但是有一个问题就是,vuex的存储的数据只是在页面的中,相当于我们定义的全局变量,刷新之后,里边的数据就会恢复到初始化状态,但是这个情况有时候并不是我们所希望的
解决方案
监听页面是否刷新,如果页面刷新了,将state对象存入到sessionStorage中,页面打开之后,判断sessionStorage 中是否存在state对象,如果存在,则说明页面是被刷新过的,将sessionStorage中存的数据取出来,给vuex中的 state赋值,如果不存在,说明是第一次打开,则取vuex中定义的state初始值
修改代码
在App.vue中,增加监听刷新事件↓
export default {
name: 'App',
mounted() {
window.addEventListener('unload', this.saveState);//监听刷新事件,刷新调用下面的saveState方法↓
},
methods: {
saveState() {//页面刷新了,将state对象存入到sessionStorage中↓
sessionStorage.setItem('state', JSON.stringify(this.$store.state));
}
}
}
修改store/index.js中的state↓
//页面打开之后,判断sessionStorage 中是否存在state对象,如果存在,则说明页面是被刷新过的,将sessionStorage中存的数据取出来,给vuex中的 state赋值,如果不存在,说明是第一次打开,则取vuex中定义的state初始值↓
const state = sessionStorage.getItem('state') ? JSON.parse(sessionStorage.getItem('state')) : {
user: {
name: ''
}
};
//增加登录成功,存储状态,以便于在下面跳转到的页面组件中,取出来↓ var user={name:vm.ruleForm.username};//写这么写,后面可以修改后端接口返回用户对象即可! vm.$store.dispatch('asyncUpdateUser', user);
2
当前登录的用户是:{{username}} username:this.$store.getters.getUser.name
7解决浏览器刷新后Vuex数据消失问题↓
在App.vue中,增加监听刷新事件↓
export default {
name: 'App',
mounted() {
window.addEventListener('unload', this.saveState);//监听刷新事件,刷新调用下面的saveState方法↓
},
methods: {
saveState() {//页面刷新了,将state对象存入到sessionStorage中↓
sessionStorage.setItem('state', JSON.stringify(this.$store.state));
}
}
}
修改store/index.js中的state↓
//页面打开之后,判断sessionStorage 中是否存在state对象,如果存在,则说明页面是被刷新过的,将sessionStorage中存的数据取出来,给vuex中的 state赋值,如果不存在,说明是第一次打开,则取vuex中定义的state初始值↓
const state = sessionStorage.getItem('state') ? JSON.parse(sessionStorage.getItem('state')) : {
user: {
name: ''
}
};