list = hotelService.list();
+ BulkRequest request = new BulkRequest();
+ // 添加采用indexRequest
+ for (Hotel hotel : list) {
+ // 转为HotelDoc并添加
+ HotelDoc hotelDoc = new HotelDoc(hotel);
+ // 添加到请求
+ request.add(new IndexRequest("hotel")
+ .id(hotelDoc.getId().toString())
+ .source(JSON.toJSONString(hotelDoc)));
+ }
+ client.bulk(request,RequestOptions.DEFAULT);
+}
+```
+
+### 总结
+
+文档操作的基本步骤:
+
+- 初始化RestHighLevelClient
+- 创建xxxRequest。xxx是Index、Get、Update、Delete
+- 准备参数(Index和Update时需要)
+- 发送请求。调用RestHighLevelClient.xxx(),xxx是index、get、update、delete
+- 解析结果(GET需要)
+
diff --git a/public/markdowns/SpringSecurity.md b/public/markdowns/SpringSecurity.md
new file mode 100644
index 0000000..14fad35
--- /dev/null
+++ b/public/markdowns/SpringSecurity.md
@@ -0,0 +1,228 @@
+---
+title: SpringSecurity
+abbrlink: 7d2eec83
+date: 2023-10-26 22:38:08
+tags:
+categories:
+ - 安全
+description: SpringSecurity
+---
+
+# SpringSecurity简介
+
+Spring是一个很棒的Java应用开发框架,Spring Security 基于Spring框架,提供了一套Web应用安全性的完整解决方案,一般来说,web应用的安全性包括**用户认证(Authenticaiton)和用户授权(Authorization)**两个部分
+
+- 用户认证指的是验证某个用户是否为系统中的合法主体,也就是说,该用户能否访问该系统,用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程
+- 用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限
+
+在用户认证方面,Spring Security框架支持主流的认证方式,包括Http基本认证、Http表单验证、Http摘要认证、OpenID和LDAP等。在用户授权方面。Spring Security提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制
+
+Spring Security是一套安全框架,可以基于RBAC(基于角色的权限控制)对用户的访问权限进行控制
+
+核心思想是通过一系列的filter chain来进行拦截过滤,对用户的访问权限进行控制
+
+spring security的核心功能主要包括:
+
+- 认证(你是谁)
+- 授权(你能干什么)
+- 攻击防护(防止伪造身份)
+
+其核心就是一组过滤器链,项目启动后将会自动配置。最核心的就是Basic Authentication Filter用来认证用户的身份,一个在spring security 中一种过滤器处理一种认证方式
+
+
+
+比如,对于username password认证过滤器来说,
+
+```
+会检查是否是一个登录请求;
+是否包含username和password(也就是该过滤器需要的一些认证信息);
+如果不满足则放行给下一个;
+下一个按照自身的职责判定是否是自身需要的信息,basic的特征就是在请求头中有Authorization:Basic eHh4Onh4的信息。中间可能还有更多的认证过滤器。最后一环是FilterSecurityInterceptor,这里会判定该请求是否能进行访问rest服务,判断的依据是BrowserSecurityConfig中的配置,如果被拒绝了就会抛出不同的异常(根据具体的原因),Exception Translation Filter会捕获抛出的错误,然后根据不同的认证方式进行信息的返回提示
+从Exception Translation Filter到最后的过滤器都无法控制,其他的可以进行配置是否生效
+```
+
+
+
+# 认证和授权
+
+ 一般来说的应用访问安全性,都是围绕认证(Authentication)和授权(Authorization)这两个核心概念来展开
+
+即:
+
+- 首先需要确认用户身份
+- 再确认用户是否有访问指定资源的权限
+
+认证这块的解决方案有很多,主流的有`CAS`、`SAML2`、`OAUTH2`等,常说的单点登录方案(SSO)就是这块授权的话,主流一般是spring security和shiro
+
+shiro比较轻量级,相比较而言spring security 架构比较复杂
+
+## OAuth2
+
+OAuth2是一个关于授权的开放标准,核心思路是通过各类认证手段认证用户身份
+
+并颁发token(令牌),使得第三方应用可以使用该令牌在**限定时间、限定范围**访问**指定资源**
+
+主要涉及RFC规范有【`RFC6748`(整体授权框架)】、【`RFC6750`(令牌使用)】、【`RFC6819`(威胁模型)】这几个,一般需要了解的是`RFC6749`
+
+获取令牌的方式主要有四种,分别是`授权码模式`、`简单模式`、`密码模式`、`客户端模型`
+
+总之:OAuth2是一个授权(Authorization)协议。
+
+认证(Authentication)证明你是不是这个人,而授权(Authoration)则是证明这个人有没有访问这个资源(Resource)的权限。
+
+### OAuth2的抽象流程
+
+ +--------+ +---------------+
+ | |--(A)- Authorization Request ->| Resource |
+ | | | Owner |
+ | |<-(B)-- Authorization Grant ---| |
+ | | +---------------+
+ | |
+ | | +---------------+
+ | |--(C)-- Authorization Grant -->| Authorization |
+ | Client | | Server |
+ | |<-(D)----- Access Token -------| |
+ | | +---------------+
+ | |
+ | | +---------------+
+ | |--(E)----- Access Token ------>| Resource |
+ | | | Server |
+ | |<-(F)--- Protected Resource ---| |
+ +--------+ +---------------+
+
+上面的图是一张来自OAuth2的抽象流程图
+
+Client:客户端应用程序(Application)
+
+Authorization Server:授权服务器
+
+Resource Server:资源服务器
+
+解释上图的大致流程:
+
+- 用户连接客户端应用程序后,客户端应用程序(Client)要求用户给予授权
+- 用户同意给予客户端应用程序授权
+- 客户端应用程序使用上一步获得的授权(Grant),向授权服务器申请令牌
+- 授权服务器对客户端应用程序的授权(Grant)进行验证后,确认无误,发放令牌
+- 客户端应用程序使用令牌,向资源服务器申请获取资源
+- 资源服务器确认令牌无误,同意向客户端应用程序开放资源
+
+其实流程无非如下,用户连接-->客户端-->客户端要求用户给出授权-->客户端拿授权申请令牌-->授权服务器校验授权无误后发放令牌-->客户端拿着令牌,找资源服务器要资源-->资源服务器校验令牌无误后发放资源
+
+从上面的流程可以看出,如何获取**授权(Grant)**才是关键。拥有正确的授权(Authorzation)就可以去拿到任意的东西了
+
+### OAuth2的4种授权类型
+
+#### Authorization Code(授权码模式)
+
+功能最完整、流程最严密的授权模式。通过第三方应用程序服务器与认证服务器进行互动。广泛用于各种第三方认证。
+
+ +----------+
+ | Resource |
+ | Owner |
+ | |
+ +----------+
+ ^
+ |
+ (B)
+ +----|-----+ Client Identifier +---------------+
+ | -+----(A)-- & Redirection URI ---->| |
+ | User- | | Authorization |
+ | Agent -+----(B)-- User authenticates --->| Server |
+ | | | |
+ | -+----(C)-- Authorization Code ---<| |
+ +-|----|---+ +---------------+
+ | | ^ v
+ (A) (C) | |
+ | | | |
+ ^ v | |
+ +---------+ | |
+ | |>---(D)-- Authorization Code ---------' |
+ | Client | & Redirection URI |
+ | | |
+ | |<---(E)----- Access Token -------------------'
+ +---------+ (w/ Optional Refresh Token)
+ Note: The lines illustrating steps (A), (B), and (C) are broken into
+ two parts as they pass through the user-agent.
+
+- 用户(Resource Owner)通过用户代理(User-Agent)访问客户端(Client),客户端索要授权,并将用户导向认证服务器(Authorization Server)
+- 用户选择是否给予客户端授权
+- 假设用户给予授权,认证服务器将用户导向客户端事先指定的**重定向URI**,同时附上一个授权码
+- 客户端收到授权码,附上早先的**重定向URI**,向认证服务器申请令牌。这一步是在客户端的后台服务器上完成的,对用户不可见
+- 认证服务器核对授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。这一步对用户也不可见
+
+#### Implicit(简化模式)
+
+不通过第三方应用程序服务器,直接在浏览器中向认证服务器申请令牌,更适用于移动端的App及没有服务器端的第三方单页面应用。
+
+##### Resource Owner Password(密码模式)
+
+用户向客户端服务器提供自己的用户名和密码,用户对客户端高度信任的情况下使用,比如公司、组织的内部系统,SSO
+
+ +----------+
+ | Resource |
+ | Owner |
+ | |
+ +----------+
+ v
+ | Resource Owner
+ (A) Password Credentials
+ |
+ v
+ +---------+ +---------------+
+ | |>--(B)---- Resource Owner ------->| |
+ | | Password Credentials | Authorization |
+ | Client | | Server |
+ | |<--(C)---- Access Token ---------<| |
+ | | (w/ Optional Refresh Token) | |
+ +---------+ +---------------+
+
+ Figure 5: Resource Owner Password Credentials Flow
+
+- 用户(Resource Owner资源持有者)向客户端(Client)提供用户名和密码
+- 客户端将用户名和密码发给认证服务器(Authorization Server),向后者请求令牌
+- 认证服务器确认无误后,向客户端提供访问令牌
+
+#### Client Credentials(客户端模式)
+
+客户端服务器以自己的名义,而不是以用户的名义,向认证服务器进行认证
+
+## 令牌刷新
+
+```
+ +--------+ +---------------+
+ | |--(A)------- Authorization Grant --------->| |
+ | | | |
+ | |<-(B)----------- Access Token -------------| |
+ | | & Refresh Token | |
+ | | | |
+ | | +----------+ | |
+ | |--(C)---- Access Token ---->| | | |
+ | | | | | |
+ | |<-(D)- Protected Resource --| Resource | | Authorization |
+ | Client | | Server | | Server |
+ | |--(E)---- Access Token ---->| | | |
+ | | | | | |
+ | |<-(F)- Invalid Token Error -| | | |
+ | | +----------+ | |
+ | | | |
+ | |--(G)----------- Refresh Token ----------->| |
+ | | | |
+ | |<-(H)----------- Access Token -------------| |
+ +--------+ & Optional Refresh Token +---------------+
+```
+
+- 客户端找授权服务器索要授权
+
+- 当用户同意给予授权后,授权服务器给予令牌,并给予刷新令牌
+
+- 此时通过令牌去资源服务器中获取资源
+
+- 得到资源
+
+ 假设token过期
+
+- 再次获取资源,发现Token无效了
+- 通过刷新令牌去授权服务器中获取Token
+- 通过Token再次获取令牌和刷新令牌,重复流程
+
diff --git a/public/markdowns/Vue.md b/public/markdowns/Vue.md
new file mode 100644
index 0000000..74b7656
--- /dev/null
+++ b/public/markdowns/Vue.md
@@ -0,0 +1,11821 @@
+---
+title: Vue2
+tags:
+ - Vue2
+categories:
+ - 前端
+description: Vue2
+abbrlink: 4d45ebbb
+---
+# Vue核心
+
+## 搭建Vue环境
+
+先在此处附上Vue的安装教程地址:https://v2.cn.vuejs.org/v2/guide/installation.html
+
+这里有两个版本,一个开发版本,一个生产版本
+
+开发版本是在开发时使用的,当出现问题的时候会在控制台报警告
+
+生产版本是在项目上线时使用的,不会有警告,而且体积更小
+
+![image-20230919083405727](https://s2.loli.net/2023/09/19/xHtPB7nUyQM3VSF.png)
+
+在这里,我使用的是开发版本,学习一般使用开发版
+
+将开发版本下载后保存到本地,使用方法与jquery是一致的,使用来script引入
+
+### 直接用script引入
+
+创建一个文件夹,在里面创建一个html文件
+
+然后直接引入vue文件即可
+
+```html
+
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+```
+
+运行文件
+
+### 消除开发环境提示
+
+在console里查看
+
+![image-20230919084602099](https://s2.loli.net/2023/09/19/9Jxbg6RQjyc3O7o.png)
+
+第一个是说下载vue的开发者工具来达到一个更好的开发者体验
+
+第二个是说你正在运行开发环境,请你确信在生产环境不要这样做
+
+两个小提示,但是不影响,后面再解决
+
+如果成功引入了Vue,在console上写入Vue会输出其对应的函数
+
+![image-20230919084937292](https://s2.loli.net/2023/09/19/nKf9Jtj4aDRyeiF.png)
+
+解决第一个提示的方法是下载一个vue的开发者工具即可
+
+vue开发者工具的github链接如下:https://github.com/vuejs/devtools#vue-devtools
+
+找到下面这个地方,点击进入谷歌商店下载
+
+![image-20230919085712128](https://s2.loli.net/2023/09/19/3nEbhJ4U2wc6siS.png)
+
+![image-20230919085756365](https://s2.loli.net/2023/09/19/7fbN283qnAHY1hv.png)
+
+第二个提示需要在代码中对其进行配置
+
+```vue
+
+```
+
+## 模板语法
+
+Vue模板语法有2大类:
+
+1. 插值语法:
+
+ 功能:用于解析标签体内容
+
+ 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性
+
+2. 指令语法:
+
+ 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件等)
+
+ 举例:v-bind:hreft="xxx"或简写为:href="xxx",xxx同样要写js表达式。且可以直接读取到data中的所有属性
+
+ 备注:Vue中有很多的指令,且形式都是:v-?????
+
+### 插值语法
+
+```html
+
+
+
+
+
+
+
+ Document
+
+
+
+
+
+ {{test}}
+
+
+
+
+
+
+```
+
+### 指令语法
+
+#### v-bind
+
+单向绑定数据
+
+```html
+
+
+
+
+
+```
+
+可以简写为`跳转到百度`
+
+```html
+
+
+
+
+
+```
+
+
+
+## 数据绑定
+
+v-bind:单向数据绑定
+
+v-model:双向数据绑定
+
+Vue中有2种数据绑定的方式:
+
+1. 单向绑定(v-bind):数据只能从data流向页面
+
+2. 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
+
+ 备注:
+
+ 1. 双向绑定一般都应用在表单类元素上(如:input、select等)
+ 2. v-model:value 可以简写为v-model,因为v-model默认收集的就是value值
+
+
+
+- el有两种写法
+
+ 1. new Vue时配置el属性
+
+ ```vue
+ new Vue({
+ // el: '#box', 第一种写法
+ })
+ ```
+
+ 2. 先创建Vue实例,随后再通过vm.$mount('#root')指定el的值
+
+ `vm.$mount('#box')`
+
+- data有2种写法
+
+ 1. 对象式
+
+ ```html
+ new Vue({
+ // el: '#box', 第一种写法
+ })
+ ```
+
+ 2. 函数式
+
+ ```html
+ // data的第二种写法:函数式
+ data() {
+ return {
+ name: 'zhangsan'
+ }
+ }
+ ```
+
+- 一个重要的原则
+
+ - 由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了
+
+v-bind的简写方式::xxx=""
+
+v-model的简写方式:v-model=""
+
+```html
+单向数据绑定:
+双向数据绑定:
+```
+
+### 单向数据绑定
+
+下面这段代码是对其进行了一个单向数据绑定,可以在页面中进行测试
+
+```html
+
+
+ 单向数据绑定:
+
+
+
+
+```
+
+之前在网上下载的Vue开发者工具此时就可以使用了
+
+打开页面后单击F12,打开这个页面,在最后一栏找到Vue
+
+
+
+在name:'zhangsan'的位置进行修改,单向数据绑定处的数据也会发生改变,而在输入框中修改,并不会改变name:'zhangsan'的内容
+
+### 双向数据绑定
+
+v-model:双向数据绑定
+
+```html
+
+
+ 单向数据绑定:
+ 双向数据绑定:
+
+
+
+
+```
+
+被绑定了双向后,在测试工具中输入任意的数据,输入框中的内容都会发生改变,或者在输入框中输入内容,也会互相的改变
+
+当输入框中的内容改变时,会带起一系列的连锁反应
+
+
+
+**注意:v-model元素只能应用在表单类元素上(输入类元素),在其他标签类元素上使用会报错**
+
+## el与data的两种写法
+
+对象式
+
+```html
+
+
+ 单向数据绑定:
+ 双向数据绑定:
+
+
+
+
+```
+
+相较之下,第二种更灵活,使用的时候两种都可以
+
+```html
+
+
+ 单向数据绑定:
+ 双向数据绑定:
+
+
+
+
+```
+
+data可以简写为下面的方式
+
+```vue
+ // data的第二种写法:函数式
+ data() {
+ return {
+ name: 'zhangsan'
+ }
+ }
+```
+
+## MVVM
+
+M:模型(Model),对应data中的数据
+
+V:视图(View), 模板
+
+VM:视图模型(ViewModel),Vue实例对象
+
+
+
+Data Bindings:数据绑定,将Model中的数据绑定到View中
+
+DOM Listeners:页面模型监听器
+
+
+
+总结:
+
+- data中所有的属性,最后都出现了Vue对象上
+- vm身上所有的属性及Vue原型上所有属性,在Vue模板中都可以直接使用
+
+
+
+## 数据代理
+
+### Object.defineProperty方法
+
+`Object.defineProperty(添加属性的对象名,添加的属性名,{value:添加的值})`
+
+```html
+
+
+
+
+```
+
+为person对象添加了一个age的属性,值为18
+
+![image-20230920132903453](https://s2.loli.net/2023/09/20/NwdsXQ17HbplYai.png)
+
+这样添加与普通的添加方式有什么区别呢,这样添加的属性是不参与遍历的
+
+正常情况下是参与遍历的
+
+```html
+
+
+
+
+```
+
+![image-20230920133350604](https://s2.loli.net/2023/09/20/XYSf5Juzpmgkrln.png)
+
+但是使用该方法进行遍历就遍历不到了
+
+```html
+
+
+
+
+```
+
+![image-20230920133321585](https://s2.loli.net/2023/09/20/bz821RoGefdhsv7.png)
+
+这种情况也叫不可枚举,如果需要遍历该怎么办呢
+
+可以在代码中加入
+
+`enumerable: true`:控制属性是否可以被枚举,默认是false
+
+```html
+
+
+
+
+```
+
+再次运行,就可以遍历到了
+
+如果你试图修改`Object.defineProperty`添加的方法,可以修改,但不会修改成功
+
+如果需要被修改怎么办呢
+
+在代码中加入`writable: true`,控制属性是否可以被修改,默认是false
+
+```html
+
+
+
+
+```
+
+数据需要被删除,可以加入`configurable: true`,控制属性是否可以被删除,默认是false
+
+#### getter和setter
+
+下面的代码提供了`Object.defineProperty`的get和set示例
+
+```html
+
+
+
+
+```
+
+
+
+
+
+### Vue中的数据代理
+
+数据代理就是让_data中的数据在Vue身上也有一份,不管是getter还是setter都可以直接通过属性名来获取使用,而不是通过 _data.属性名来使用,这样会非常的冗余,在getter时,数据代理会getter到 _data的身上,而setter时,会setter到 _data的身上,从而达到一个连锁的效果,简化了开发
+
+数据代理图示:
+
+
+
+Vue先将data中的数据存放到_data中,然后再通过`Object.defineProperty`方法将数据放到vm身上,这样就起到一个数据代理的效果
+
+```html
+
+
+
{{name}}
+ {{age}}
+
+
+
+
+```
+
+以上面这段示例代码为例,Vue中的数据代理其实也是同理的
+
+当有人访问页面中的name或age时,它会利用getter去访问data中的name或age
+
+当有人修改页面中的name或age时,它会利用setter去修改data中的name或age
+
+此时就不是直接访问,而是以一种代理的形式,通过访问Vue上的getter或setter方法来达到修改data上的数据
+
+
+
+这里对数据代理的两种形式做一个验证
+
+修改data中的属性后,查看其中vue中的data是否发生变化
+
+
+
+发现此时这里的name确实是发生改变了,这说明数据改变后,依然是从data中来获取的
+
+
+
+对setter进行一个验证
+
+修改对应的属性,然后获取其data中的属性是否发生了改变
+
+![image-20230921093045894](https://s2.loli.net/2023/09/21/k4B1dSHMEINqOw3.png)
+
+这里我们发现,修改了它的属性后,data中的属性也发生了改变,这说明setter方法是存在数据代理的,设置完的属性会放到data中
+
+
+
+总结:
+
+1. Vue中的数据代理:
+
+ 通过vm对象来代理data对象中属性的操作(读/写)
+
+2. Vue中数据代理的好处:
+
+ 更加方便的操作data中的数据
+
+3. 基本原理
+
+ 通过Object.defineProperty()把data对象中所有属性添加到vm上
+
+ 通过每一个添加到vm上的属性,都指定一个getter/setter
+
+ 在getter/setter内部去操作(读/写)data中对应的属性
+
+
+
+## 事件处理
+
+### 事件的基本使用
+
+事件的基本使用:
+
+1. 使用v-on:xxx 或 @xxx绑定事件,其中xxx是事件名
+2. 事件的回调需要配置在methods对象中,最终会在vm上
+3. methods配置的函数,不要用箭头函数,否则this就不是vm了
+4. methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象
+5. @click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参
+
+#### v-on:click
+
+**简写形式为:@click**
+
+当被点击时
+
+```html
+
+
+
+
+
+
+
+```
+
+
+
+如果需要接收参数,可以这样写
+
+```html
+
+
+
+
+
+
+
+```
+
+但是这样写event就无法使用了
+
+可以通过在传参位置加入占位符`$event`的形式传递event参数
+
+```html
+
+
+
+
+
+
+
+```
+
+### 事件修饰符
+
+正常的运行下面这段代码,会在代码运行后依然将网页跳转到了百度
+
+```html
+
+
+
+
+
+```
+
+跳转是a标签的默认行为,我们有什么好的办法来阻止这个默认行为呢
+
+可以通过`e.preventDefault`方法对这个默认行为进行阻止
+
+```html
+methods: {
+
+ jump(e) {
+
+ e.preventDefault();
+
+ alert("跳走喽")
+
+ }
+
+ },
+```
+
+也可以通过Vue中的事件修饰符
+
+1. **prevent:阻止默认事件(常用)**
+2. **stop:阻止事件冒泡(常用)**
+3. **once:事件只触发一次(常用)**
+4. capture:使用事件的捕获模式
+5. self:只有event.target是当前操作的元素时才触发事件
+6. passive:事件的默认行为立即执行,无需等待事件回调执行完毕
+
+演示一下常用的三种,其余不做演示
+
+#### prevent:
+
+**效果和`e.preventDefault();`是一样的**
+
+```html
+
+
+
+
+
+```
+
+#### stop:
+
+冒泡是从当没有返回值true或false之类时,会从里向外(向它的父元素执行其父元素的方法直到结束)
+
+冒泡情况演示
+
+```html
+
+
+
+
+
+```
+
+冒泡解决方案:
+
+```html
+
+
+
+
+
+```
+
+冒泡解决方案Vue版:
+
+```html
+
+
+
+
+
+
+```
+
+#### once:
+
+事件只触发一次,字面意思,挺好理解的
+
+```html
+
+
+
+
+
+
+
+```
+
+
+
+### 键盘事件
+
+@keyup:当键盘弹起时
+
+@keydown:当键盘按下时
+
+下面这段代码是当键盘弹起时,如果按下的是回车就打印内容在控制台上
+
+```html
+
+
+
+
+
+
+
+```
+
+这里的判断keyCode也可以置换为vue中的别名
+
+```html
+
+
+
+
+
+
+
+```
+
+#### vue常见按键别名
+
+回车 => enter
+
+删除 => delete(捕获"删除"和"退格"键)
+
+退出 => esc
+
+空格 => space
+
+换行 => tab
+
+上 => up
+
+下 => down
+
+左 => left
+
+右 => right
+
+
+
+Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
+
+短横线命名是什么意思呢?
+
+就是说,如果某个按键未提供别名,可以使用原始的key去绑定,比如CapsLock,如果想要使用的话,需要转为caps-lock,记得要在两个单词之间加入短横线-
+
+示例代码
+
+```html
+
+
+
+
+
+
+
+```
+
+
+
+特殊按键tab:按了之后会离开焦点,这种不适合在keyup上使用,因为在键盘弹起后触发时,焦点已经离开了,方法可能就无法触发了(必须配合keydown使用)
+
+
+
+系统修饰键(用法特殊):ctrl、alt、shift、meta(win)
+
+1. 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
+2. 配合keydown使用:正常触发事件
+
+
+
+也可以使用keyCode去指定具体的按键(不推荐)
+
+``
+
+
+
+Vue.config.keyCodes.自定义键名 = 键码,可以定制按键别名
+
+`Vue.config.keyCodes.huiche = 13`
+
+```html
+
+
+
+
+
+
+
+```
+
+
+
+### 事件总结
+
+- 事件修饰符可以连着写,例如@click.prevent.stop="xxx",效果是停止默认事件并阻止冒泡,但它是有先后顺序的,也就是说,先停止默认事件,再阻止冒泡,谁写在前面谁先
+- 而键盘事件也可以连着写,例如,`@keyup.ctrl.y`,连着写之后的效果就是按下特定的这两位才会触发效果,其他的没效果
+
+
+
+## 计算属性
+
+### 姓名案例
+
+插值语法实现
+
+```html
+
+
+ 姓:
+ 名:
+ 姓名: {{firstName.slice(0,3)}}-{{lastName}}
+
+
+
+
+```
+
+如果我们想为名称加一些新的效果,但是会有很多,这样就会很麻烦,如果我们把它整理成一个methods,看起来就不会特别的冗余了
+
+```html
+
+
+ 姓:
+ 名:
+ 姓名: {{name()}}
+
+
+
+
+```
+
+### 计算属性
+
+1. 定义:要用的属性不存在,要通过**已有属性(vue中的才叫属性)**计算得来
+2. 原理:底层借助了Object.defineproperty方法提供的getter和setter
+3. get函数什么时候执行?
+ - 初次读取时会执行一次
+ - 当依赖的数据发生改变时会被再次调用
+4. 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
+5. 备注:
+ 1. 计算属性最终会出现在vm上,直接读取使用即可
+ 2. 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时**依赖的数据发生改变**,否则无效
+
+使用计算属性编写之前的姓名案例
+
+ 这里的get和`Object.defineProperty`是一样的
+
+当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
+
+get什么时候调用
+
+- 初次读取fullName时
+- 所依赖的数据发生改变时
+
+```html
+
+
+ 姓:
+ 名:
+ 姓名: {{fullName}}
+
+
+
+
+```
+
+且get是有缓存的,而methods是没有缓存的,性能上computed更好一些
+
+有get肯定就有set,和get的道理其实也是一样的
+
+```html
+
+
+ 姓:
+ 名:
+ 姓名: {{fullName}}
+
+
+
+
+```
+
+### 计算属性简写
+
+简写的形式只有在**只读不改**的时候才能使用
+
+```html
+
+
+ 姓:
+ 名:
+ 姓名: {{fullName}}
+
+
+
+
+```
+
+
+
+## 监视属性
+
+### 天气案例
+
+先做一个天气的小案例,点击按钮后变换天气
+
+这里使用了计算属性来进行操作
+
+```html
+
+
+
今天天气很{{info}}
+
+
+
+
+
+```
+
+但是在这里有一个小坑
+
+如果我们将代码中的这一行改变了
+
+改变为`今天天气很一般
`
+
+此时页面上就不会用到isHot和info了,如果我们此时点击一下按钮,页面是肯定不会发生变化的,但是你打开开发者工具一看
+
+
+
+开发者工具中却是true和炎热,我们去控制台上看一下
+
+
+
+控制台上就发生了变化了
+
+这是为什么呢,原因其实是vue的开发者工具认为你页面没有使用到该数据,就没有为你更新了,这个是官方的一个bug,不影响
+
+这里写的代码其实很多,只是为了实现一个切换功能,那还有什么办法能更简单吗
+
+```html
+
+
+
今天天气很{{info}}
+
+
+
+
+
+```
+
+一些简单的代码其实可以直接使用@click来写
+
+如果你不仅想做这个操作,还想做别的操作呢,有两种方式
+
+1. 直接在methods中写
+2. `@click="isHot = !isHot";你想做的操作`
+
+比如:
+
+```html
+
+
+
今天天气很{{info}}
+
+
+
+
+
+```
+
+
+
+### 监视属性watch
+
+1. 当被监视的属性变化时,回调函数自动调用,进行相关操作
+2. 监视的属性必须存在,才能进行监视
+3. 监视的两种写法:
+ 1. new Vue时传入watch配置
+ 2. 通过vm.$watch监视
+
+```html
+
+
+
今天天气很{{info}}
+
+
+
+
+
+```
+
+监视属性是watch,是一个对象的形式,里面可以放置多个对象,每个对象里面有配置属性和handler等
+
+handler中有两个参数可以接收,第一个是newValue,第二个是oldValue
+
+除了上面这种监视属性的写法,还有另一种监视属性的写法
+
+```html
+
+```
+
+
+
+### 深度监视
+
+1. Vue中的watch**默认不监测**对象内部值的改变(一层)
+2. 配置`deep:true`可以监测对象内部值的改变(多层)
+
+备注:
+
+- **Vue自身可以**监测对象内部值的改变,但Vue提供的watch**默认不可以**
+- 使用watch时根据数据的具体结构,决定是否采用深度监视,采用深度监视会有效率的问题
+
+#### 监视多级结构中某个属性的变化
+
+当多级结构中的a发生变化时,可以获取得到它
+
+```html
+
+
+
a的值是:{{numbers.a}}
+
+
+
+
+
+```
+
+#### 检测整体结构变化
+
+```html
+
+
+
a的值是:{{numbers.a}}
+
+
+
+
+
+
+
+
+```
+
+
+
+#### 检测整体结构的任意一个值的变化
+
+为watch中的属性配置deep即可检测值的变化
+
+```html
+
+
+
a的值是:{{numbers.a}}
+
+
+
+
+
+
+
+
+```
+
+
+
+### 监视的简写形式
+
+监视的简写形式只有在仅handler的情况下才可以使用
+
+```html
+
+
+
numbers的值是:{{numbers}}
+
+
+
+
+
+```
+
+但是监视有两种写法,它还有一种vm.$watch的写法,也可以简写
+
+```html
+
+
+
numbers的值是:{{numbers}}
+
+
+
+
+
+```
+
+
+
+### watch对比computed
+
+computed和watch之间的区别:
+
+1. computed能完成的功能,watch都可以完成
+2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作(定时器)
+
+两个重要的小原则:
+
+1. 被Vue所管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
+2. 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,因为在JavaScript中,箭头函数并不会创建自己的this上下文,而是继承其所在代码块的this。因此,在Vue组件的方法中,如果我们使用了箭头函数,那么this才会指向Vue实例。
+
+watch写法的姓名案例
+
+```html
+
+
+ 姓:
+ 名:
+
姓名:{{fullName}}
+
+
+
+
+```
+
+computed写法的姓名案例
+
+```html
+
+
+ 姓:
+ 名:
+
姓名:{{fullName}}
+
+
+
+
+```
+
+
+
+## 绑定样式
+
+### 绑定class样式
+
+字符串写法,适用于:样式的类名不确定,需要动态指定
+
+可以将样式修改为指定的内容
+
+```html
+
+
+
+
+
+```
+
+也可以通过布尔值进行判断之类的情况
+
+当isActive为true时,active才会作为类生效
+
+```html
+
+
+
+
+
+```
+
+绑定计算属性作为class的判断
+
+```html
+
+
+
+
+
+```
+
+这段代码的释义是使用了一个计算属性
+
+计算属性的含义是classObject,当满足isActive为true并且error不为空的条件时,返回active;当error存在并且error的类型为fatal时返回text-danger
+
+### 数组语法
+
+我们可以把一个数组传给v-bind:class,来应用一个class列表的情况
+
+```html
+
+
+
+
+
+```
+
+最终它会渲染为`class='activeClass isYes'`
+
+如果想根据条件来切换数组语法中的内容,也是可以的
+
+```html
+test
+```
+
+可以通过三元表达式来对其进行修改
+
+如果觉得三元表达式不够友好,可以采取对象语法的方式
+
+```html
+test
+```
+
+
+
+### 绑定内联样式
+
+#### 对象语法
+
+```html
+
+
+
+
+
+```
+
+或者将样式绑定到一个对象中,直接使用对象
+
+```html
+hahahha
+```
+
+```js
+data: {
+ styleData: {
+ backgroundColor: 'red',
+ fontSize: '30px'
+ }
+ }
+```
+
+#### 数组语法
+
+将多个样式对象绑定到一个数组上
+
+```html
+hahahha
+```
+
+#### 多重值
+
+从vue2.3.0开始可以为style绑定中的property提供一个包含多个值的数组,常用于提供多个带前缀的值,例如:
+
+```html
+
+```
+
+`'-webkit-box,'-ms-flexbox','flex'`是不同浏览器支持的类型前缀,这样写只会渲染数组中最后一个被浏览器支持的值,如果浏览器支持不带浏览器前缀的flexbox,那么就只会渲染`display:flex`
+
+
+
+## 条件渲染
+
+### v-if、v-else
+
+`v-if` 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true值的时候被渲染。
+
+`v-else`的效果是当if不生效时,else生效
+
+`v-else` 元素必须紧跟在带 `v-if` 或者 `v-else-if` 的元素的后面,否则它将不会被识别。
+
+```html
+
+
+
+
+
+```
+
+### 在``元素上使用v-if渲染分组
+
+因为`v-if`是一个指令,所以必须将它添加到一个元素上,但是如果想切换多个元素呢,此时可以把一个``元素当作不可见的包裹元素,并在上面使用`v-if`。最终的渲染结果不包含``元素
+
+```html
+
+
+
+
+ title
+ 1
+ 2
+
+
+
+
+
+
+```
+
+
+
+### v-else-if
+
+**2.1.0 新增**
+
+类似于 `v-else`,`v-else-if` 也必须紧跟在带 `v-if` 或者 `v-else-if` 的元素之后。
+
+```html
+
+
+
+ 成绩在90分及以上
+
+
+ 成绩在70分及以上
+
+
+ 成绩在50分及以上
+
+
+ 成绩在0分及以上
+
+
+
+
+
+```
+
+### 用key管理可复用的元素
+
+Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使 Vue 变得非常快之外,还有其它一些好处。例如,如果你允许用户在不同的登录方式之间切换:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+那么在上面的代码中切换 `loginType` 将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,`` 不会被替换掉——仅仅是替换了它的 `placeholder`。
+
+这样会起到复用input输入框的作用
+
+如果我们想让这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 `key` attribute 即可:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+`