rabbitmq
|
@ -0,0 +1,27 @@
|
||||||
|
大对象,新生代存储不下的对象,分配担保直接到老年代。
|
||||||
|
|
||||||
|
1. 年龄超过15
|
||||||
|
2. 相同年龄超过50%
|
||||||
|
3. 动态年龄分配,不同年龄特别多。
|
||||||
|
4. 内存担保,新生代垃圾回收无法完成,直接放入老年代。 **在GC前还会进行一次判断,如果要分配的内存>=Eden区大小的一半,那么会直接把要分配的内存放入老年代中。否则才会进入担保机制。**
|
||||||
|
|
||||||
|
TLAB的全称是Thread Local Allocation Buffer,即线程本地分配缓存区,这是一个线程专用的内存分配区域。
|
||||||
|
|
||||||
|
java -XX:+PrintCommandLineFlags -version
|
||||||
|
|
||||||
|
什么样的对象要被GC
|
||||||
|
|
||||||
|
判断回收算法
|
||||||
|
|
||||||
|
- 引用计数法,相互引用,循环引用
|
||||||
|
- 可达性分析,GCroot(本地变量表引用对象,用来关联对象关系、方法区中的静态变量和常量,虚拟机栈中本地变量表(局部变量),static成员,常量引用,本地方法栈中变量,类加载器,Thread)。
|
||||||
|
- 不可达对象,finalize可以挽回一次防止回收。
|
||||||
|
- 本地方法栈中JNI引用的对象
|
||||||
|
|
||||||
|
### 对象头内存分配
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
|
@ -0,0 +1,9 @@
|
||||||
|
## GC范围
|
||||||
|
|
||||||
|
GC管理的主要区域是Java堆,一般情况下只针对堆进行垃圾回收。方法区、栈和本地方法区不被GC所管理,因而选择这些区域内的对象的引用作为GC roots,被GC roots引用的对象不被GC回收。
|
||||||
|
|
||||||
|
## 垃圾收集器
|
||||||
|
|
||||||
|
- 并行parallel:多个垃圾收集线程并行工作,此时用户线程处于等待状态。
|
||||||
|
- 并发concurrent:用户线程和垃圾收集线程同时执行。
|
||||||
|
- 吞吐量:用户代码执行时间/(用户代码执行时间+垃圾收集时间)
|
59
jvm/JVM简介.md
|
@ -1,28 +1,28 @@
|
||||||
# JVM简介
|
# JVM简介
|
||||||
|
|
||||||
write once run everywhere
|
优势:
|
||||||
|
|
||||||
|
1. write once run everywhere
|
||||||
|
2. 内存管理
|
||||||
|
|
||||||
## jvm空间加载运行
|
## jvm空间加载运行
|
||||||
|
|
||||||
参考jvm规范:https://docs.oracle.com/javase/specs/index.html
|
参考jvm规范:https://docs.oracle.com/javase/specs/index.html
|
||||||
|
|
||||||
### 空间、运行时数据区
|
-
|
||||||
|
|
||||||
- 线程共享
|
|
||||||
- Heap堆:在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。存储数据不是线程安全的,<u>**堆和常量池**</u>空间不足时会触发OutOfMemoryError
|
|
||||||
- MetaSpace元数据区:在1.8之后取代Method Area 方法区永久代,不在jvm中,使用本地内存,受操作系统内存限制。存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
|
|
||||||
- 线程隔离
|
|
||||||
- VM Stack虚拟机栈:每个线程创建一个单独的运行时堆栈。对于每一个方法调用,一个称为栈内存栈帧被创建。所有局部变量将被创建在栈内存中。栈区域时线程安全的,因为他不是一个共享资源。
|
|
||||||
- Navive Method Stack本地方法栈:与虚拟机所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
|
|
||||||
- Program Counter Register 程序计数器:每个线程必须分开程序计数器登记,当前执行的指令一旦被执行,程序计数器更新下一个指令。一块较小的内存空间。他的作用可以看做是当前线程所执行的字节码的行号指示器。
|
|
||||||
|
|
||||||
### 加载
|
### 加载
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
- 类加载器
|
- 类加载器
|
||||||
- Bootstrap:加载环境变量中$JAVA_HOME/jre/lib/rt.jar里所有的class,不是ClassLoader子类。
|
- Bootstrap:加载环境变量中$JAVA_HOME/jre/lib/rt.jar里所有的class,不是ClassLoader子类。
|
||||||
- Extension:加载java平台中扩展功能的一些jar包。包括环境变量中$JAVA_HOME/jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包。
|
- Extension:加载java平台中扩展功能的一些jar包。包括环境变量中$JAVA_HOME/jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包。
|
||||||
- Application:加载classpath中指定的jar包及目录中class。
|
- Application:加载classpath中指定的jar包及目录中class。
|
||||||
- Custom自定义:应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行是实现ClassLoader
|
- Custom自定义:应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行是实现ClassLoader
|
||||||
|
- 双亲委派
|
||||||
|
- 写类String写main方法无法启动,Bootstrap Class Loader 中已经加载了String,其中无main方法,无法启动。委派给父类,所有父类都加载不到才会有子类加载。不让jdk代码被修改。
|
||||||
|
|
||||||
|
|
||||||
### 链接
|
### 链接
|
||||||
|
|
||||||
|
@ -34,12 +34,39 @@ write once run everywhere
|
||||||
|
|
||||||
- 类或接口的初始化由执行类或接口初始化方法构成,这里所有的静态变量与原来的值将被指派,静态块将被执行。
|
- 类或接口的初始化由执行类或接口初始化方法构成,这里所有的静态变量与原来的值将被指派,静态块将被执行。
|
||||||
|
|
||||||
|
### 线程空间
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- 线程共享
|
||||||
|
- Heap堆:在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。存储数据不是线程安全的,<u>**堆和常量池**</u>空间不足时会触发OutOfMemoryError
|
||||||
|
- MetaSpace元数据区:在1.8之后取代Method Area 方法区永久代,不在jvm中,使用本地内存,受操作系统内存限制。存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
|
||||||
|
- 线程隔离
|
||||||
|
- VM Stack虚拟机栈:每个线程创建一个单独的运行时堆栈。对于每一个方法调用,一个称为栈内存栈帧被创建。所有局部变量将被创建在栈内存中。栈区域时线程安全的,因为他不是一个共享资源。
|
||||||
|
- Navive Method Stack本地方法栈:与虚拟机所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
|
||||||
|
- Program Counter Register 程序计数器:每个线程必须分开程序计数器登记,当前执行的指令一旦被执行,程序计数器更新下一个指令。一块较小的内存空间。他的作用可以看做是当前线程所执行的字节码的行号指示器。
|
||||||
|
|
||||||
|
### 运行时数据区
|
||||||
|
|
||||||
|
- 程序计数器:指向当前线程正在执行的字节码指令的地址和行号
|
||||||
|
|
||||||
|
- 虚拟机栈:存储当前线程运行方法所需的数据、指令、返回地址(动态链接,注入使用查找实例)。
|
||||||
|
|
||||||
|
- - 栈帧:局部变量表,操作数栈、动态链接、出口
|
||||||
|
- javap -c -v .class > p.txt
|
||||||
|
|
||||||
|
- 本地方法 native
|
||||||
|
|
||||||
|
- 方法区 类信息、常量、静态变量、JIT(just in time)编译时信息(永久代对方法的实现)
|
||||||
|
|
||||||
|
- Heap 堆(内存模型)存放new出来的对象
|
||||||
|
|
||||||
|
- - 新生代
|
||||||
|
- 老年代
|
||||||
|
- 永久代/元数据区(方法区、非堆)
|
||||||
|
|
||||||
## 内存空间分配
|
## 内存空间分配
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 垃圾收集器
|
|
||||||
|
|
||||||
- 并行parallel:多个垃圾收集线程并行工作,此时用户线程处于等待状态。
|
|
||||||
- 并发concurrent:用户线程和垃圾收集线程同时执行。
|
|
||||||
- 吞吐量:用户代码执行时间/(用户代码执行时间+垃圾收集时间)
|
|
||||||
|
|
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 114 KiB |
After Width: | Height: | Size: 182 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 123 KiB |
|
@ -0,0 +1,25 @@
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
https://www.rabbitmq.com/install-debian.html
|
||||||
|
|
||||||
|
## 启动
|
||||||
|
|
||||||
|
```shell
|
||||||
|
## 启动
|
||||||
|
systemctl start rabbitmq-server
|
||||||
|
## 启动web ui
|
||||||
|
rabbitmq-plugins enable rabbitmq_management
|
||||||
|
## 启动websocket
|
||||||
|
rabbitmq-plugins enable rabbitmq_web_stomp
|
||||||
|
|
||||||
|
# create a user
|
||||||
|
rabbitmqctl add_user full_access s3crEt
|
||||||
|
# tag the user with "administrator" for full management UI and HTTP API access
|
||||||
|
rabbitmqctl set_user_tags full_access administrator
|
||||||
|
```
|
||||||
|
|
||||||
|
## 端口
|
||||||
|
|
||||||
|
https://www.rabbitmq.com/install-debian.html
|
||||||
|
|
||||||
|

|
|
@ -0,0 +1,24 @@
|
||||||
|
# debug findAll
|
||||||
|
|
||||||
|
1. JpaSpecificationExecutor::Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);
|
||||||
|
2. SimpleJpaRepository::public Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable)
|
||||||
|
3. CriteriaQueryTypeQueryAdapter::getResultList()
|
||||||
|
4. AbstractProducedQuery::list()
|
||||||
|
5. AbstractProducedQuery::beforeQuery()
|
||||||
|
6. 执行第一条sql:final PreparedStatement st = prepareQueryStatement( sql, queryParameters, limitHandler, scroll, session );
|
||||||
|
|
||||||
|
根据结果获取内容
|
||||||
|
|
||||||
|
```java
|
||||||
|
final List results = getRowsFromResultSet(
|
||||||
|
rs,
|
||||||
|
queryParameters,
|
||||||
|
session,
|
||||||
|
returnProxies,
|
||||||
|
forcedResultTransformer,
|
||||||
|
maxRows,
|
||||||
|
nullSeparatedHydratedObjectsPerRow,
|
||||||
|
subselectResultKeys
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
#### 绑定 v-bind
|
||||||
|
|
||||||
|
v-bind attribute :将这个元素节点的 `title` attribute 和 Vue 实例的 `message` property 保持一致
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
<div id="app-2">
|
||||||
|
<span v-bind:title="message">
|
||||||
|
鼠标悬停几秒钟查看此处动态绑定的提示信息!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
var app2 = new Vue({
|
||||||
|
el: '#app-2',
|
||||||
|
data: {
|
||||||
|
message: '页面加载于 ' + new Date().toLocaleString()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
在控制台输入改变信息:app2.message = '新消息'
|
||||||
|
|
||||||
|
#### 控制元素显示 v-if
|
||||||
|
|
||||||
|
```js
|
||||||
|
<div id="app-3">
|
||||||
|
<p v-if="seen">现在你看到我了</p>
|
||||||
|
</div>
|
||||||
|
var app3 = new Vue({
|
||||||
|
el: '#app-3',
|
||||||
|
data: {
|
||||||
|
seen: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
直接在控制台改变属性:app3.seen = false
|
||||||
|
|
||||||
|
#### 循环展示 v-for
|
||||||
|
|
||||||
|
```js
|
||||||
|
<div id="app-4">
|
||||||
|
<ol>
|
||||||
|
<li v-for="todo in todos">
|
||||||
|
{{ todo.text }}
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
var app4 = new Vue({
|
||||||
|
el: '#app-4',
|
||||||
|
data: {
|
||||||
|
todos: [
|
||||||
|
{ text: '学习 JavaScript' },
|
||||||
|
{ text: '学习 Vue' },
|
||||||
|
{ text: '整个牛项目' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
在控制台改变内容:app4.todos.push({ text: '新项目' })
|
||||||
|
|
||||||
|
#### 添加一个事件监听器 v-on
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
<div id="app-5">
|
||||||
|
<p>{{ message }}</p>
|
||||||
|
<button v-on:click="reverseMessage">反转消息</button>
|
||||||
|
</div>
|
||||||
|
var app5 = new Vue({
|
||||||
|
el: '#app-5',
|
||||||
|
data: {
|
||||||
|
message: 'Hello Vue.js!'
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
reverseMessage: function () {
|
||||||
|
this.message = this.message.split('').reverse().join('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 表单输入和应用状态之间的双向绑定 v-model
|
||||||
|
|
||||||
|
```js
|
||||||
|
<div id="app-6">
|
||||||
|
<p>{{ message }}</p>
|
||||||
|
<input v-model="message">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
var app6 = new Vue({
|
||||||
|
el: '#app-6',
|
||||||
|
data: {
|
||||||
|
message: 'Hello Vue!'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 组件
|
||||||
|
|
||||||
|
- 任意类型的应用界面都可以抽象为一个组件树。
|
||||||
|
|
||||||
|
- 子单元通过 prop 接口与父单元进行了良好的解耦。
|
||||||
|
|
||||||
|
- 所有的 Vue 组件都是 Vue 实例。
|
||||||
|
|
||||||
|
```js
|
||||||
|
Vue.component('todo-item', {
|
||||||
|
// todo-item 组件现在接受一个
|
||||||
|
// "prop",类似于一个自定义 attribute。
|
||||||
|
// 这个 prop 名为 todo。
|
||||||
|
props: ['todo'],
|
||||||
|
template: '<li>{{ todo.text }}</li>'
|
||||||
|
})
|
||||||
|
|
||||||
|
<div id="app-7">
|
||||||
|
<ol>
|
||||||
|
<!--
|
||||||
|
现在我们为每个 todo-item 提供 todo 对象
|
||||||
|
todo 对象是变量,即其内容可以是动态的。
|
||||||
|
我们也需要为每个组件提供一个“key”,稍后再
|
||||||
|
作详细解释。
|
||||||
|
-->
|
||||||
|
<todo-item
|
||||||
|
v-for="item in groceryList"
|
||||||
|
v-bind:todo="item"
|
||||||
|
v-bind:key="item.id"
|
||||||
|
></todo-item>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
var app7 = new Vue({
|
||||||
|
el: '#app-7',
|
||||||
|
data: {
|
||||||
|
groceryList: [
|
||||||
|
{ id: 0, text: '蔬菜' },
|
||||||
|
{ id: 1, text: '奶酪' },
|
||||||
|
{ id: 2, text: '随便其它什么人吃的东西' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应式
|
||||||
|
|
||||||
|
- 当一个 Vue 实例被创建时,它将 `data` 对象中的所有的 property 加入到 Vue 的**响应式系统**中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
|
||||||
|
- 值得注意的是只有当实例被创建时就已经存在于 `data` 中的 property 才是**响应式**的。
|
||||||
|
- `Object.freeze()`,这会阻止修改现有的 property,也意味着响应系统无法再*追踪*变化。
|
||||||
|
|
||||||
|
```js
|
||||||
|
var obj = {
|
||||||
|
foo: 'bar'
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.freeze(obj)
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
data: obj
|
||||||
|
})
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<p>{{ foo }}</p>
|
||||||
|
<!-- 这里的 `foo` 不会更新! -->
|
||||||
|
<button v-on:click="foo = 'baz'">Change it</button>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
- 除了数据 property,Vue 实例还暴露了一些有用的实例 property 与方法。它们都有前缀 `$`,以便与用户定义的 property 区分开来。
|
||||||
|
|
||||||
|
```js
|
||||||
|
var data = { a: 1 }
|
||||||
|
var vm = new Vue({
|
||||||
|
el: '#example',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
|
||||||
|
vm.$data === data // => true
|
||||||
|
vm.$el === document.getElementById('example') // => true
|
||||||
|
|
||||||
|
// $watch 是一个实例方法
|
||||||
|
vm.$watch('a', function (newValue, oldValue) {
|
||||||
|
// 这个回调将在 `vm.a` 改变后调用
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 生命周期钩子
|
||||||
|
|
||||||
|
- 生命周期钩子的 `this` 上下文指向调用它的 Vue 实例。
|
||||||
|
- 不要在选项 property 或回调上使用箭头函数
|
||||||
|
|
||||||
|
```js
|
||||||
|
new Vue({
|
||||||
|
data: {
|
||||||
|
a: 1
|
||||||
|
},
|
||||||
|
created: function () {
|
||||||
|
// `this` 指向 vm 实例
|
||||||
|
console.log('a is: ' + this.a)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// => "a is: 1"
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,[直接写渲染 (render) 函数](https://cn.vuejs.org/v2/guide/render-function.html),使用可选的 JSX 语法。
|
||||||
|
|
||||||
|
#### 数据绑定
|
||||||
|
|
||||||
|
- 数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值。
|
||||||
|
- 通过使用 [v-once 指令](https://cn.vuejs.org/v2/api/#v-once),你也能执行一次性地插值,当数据改变时,插值处的内容不会更新,类似Object.freeze()。但请留心这会影响到该节点上的其它数据绑定。
|
||||||
|
|
||||||
|
```js
|
||||||
|
<span>Message: {{ msg }}</span>
|
||||||
|
<span v-once>这个将不会改变: {{ msg }}</span>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### v-html
|
||||||
|
|
||||||
|
- 双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令
|
||||||
|
|
||||||
|
```js
|
||||||
|
<p>Using mustaches: {{ rawHtml }}</p>
|
||||||
|
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### v-bind
|
||||||
|
|
||||||
|
- Mustache 语法不能作用在 HTML attribute 上,遇到这种情况应该使用 v-bind
|
||||||
|
|
||||||
|
```js
|
||||||
|
<div v-bind:id="dynamicId"></div>
|
||||||
|
// 如果 isButtonDisabled 的值是 null、undefined 或 false,则 disabled attribute 甚至不会被包含在渲染出来的 <button> 元素中。
|
||||||
|
<button v-bind:disabled="isButtonDisabled">Button</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### javascript语法
|
||||||
|
|
||||||
|
```
|
||||||
|
{{ number + 1 }}
|
||||||
|
{{ ok ? 'YES' : 'NO' }}
|
||||||
|
{{ message.split('').reverse().join('') }}
|
||||||
|
<div v-bind:id="'list-' + id"></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
- 数据绑定支持javascript语法
|
||||||
|
- 每个绑定都只能包含**单个表达式**
|
||||||
|
- 模板表达式都被放在沙盒中,只能访问[全局变量的一个白名单](https://github.com/vuejs/vue/blob/v2.6.10/src/core/instance/proxy.js#L9),如 `Math` 和 `Date` 。你不应该在模板表达式中试图访问用户定义的全局变量。
|
||||||
|
|
||||||
|
```js
|
||||||
|
<!-- 这是语句,不是表达式 -->
|
||||||
|
{{ var a = 1 }}
|
||||||
|
<!-- 流控制也不会生效,请使用三元表达式 -->
|
||||||
|
{{ if (ok) { return message } }}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 指令v-
|
||||||
|
|
||||||
|
- 指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
|
||||||
|
|
||||||
|
```js
|
||||||
|
<p v-if="seen">现在你看到我了</p>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 参数
|
||||||
|
|
||||||
|
```js
|
||||||
|
<a v-bind:href="url">...</a>
|
||||||
|
// 在这里 href 是参数,告知 v-bind 指令将该元素的 href attribute 与表达式 url 的值绑定。
|
||||||
|
<a v-on:click="doSomething">...</a>
|
||||||
|
// 在这里参数是监听的事件名。
|
||||||
|
<a v-bind:[attributeName]="url"> ... </a>
|
||||||
|
// 这里的 attributeName 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,如果你的 Vue 实例有一个 data property // attributeName,其值为 "href",那么这个绑定将等价于 v-bind:href。
|
||||||
|
<a v-on:[eventName]="doSomething"> ... </a>
|
||||||
|
// 当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus。
|
||||||
|
```
|
||||||
|
|
||||||
|
- 在 DOM 中使用模板时 (直接在一个 HTML 文件里撰写模板),还需要避免使用大写字符来命名键名,因为浏览器会把 attribute 名全部强制转为小写
|
||||||
|
|
||||||
|
```js
|
||||||
|
<!--
|
||||||
|
在 DOM 中使用模板时这段代码会被转换为 `v-bind:[someattr]`。
|
||||||
|
除非在实例中有一个名为“someattr”的 property,否则代码不会工作。
|
||||||
|
-->
|
||||||
|
<a v-bind:[someAttr]="value"> ... </a>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 修饰符
|
||||||
|
|
||||||
|
- 修饰符 (modifier) 是以半角句号 `.` 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,`.prevent` 修饰符告诉 `v-on` 指令对于触发的事件调用 `event.preventDefault()`
|
||||||
|
|
||||||
|
```js
|
||||||
|
<form v-on:submit.prevent="onSubmit">...</form>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 缩写:@
|
||||||
|
|
||||||
|
```js
|
||||||
|
<!-- v-bind 完整语法 -->
|
||||||
|
<a v-bind:href="url">...</a>
|
||||||
|
<!-- 缩写 -->
|
||||||
|
<a :href="url">...</a>
|
||||||
|
<!-- 动态参数的缩写 (2.6.0+) -->
|
||||||
|
<a :[key]="url"> ... </a>
|
||||||
|
|
||||||
|
<!-- v-on 完整语法 -->
|
||||||
|
<a v-on:click="doSomething">...</a>
|
||||||
|
<!-- 缩写 -->
|
||||||
|
<a @click="doSomething">...</a>
|
||||||
|
<!-- 动态参数的缩写 (2.6.0+) -->
|
||||||
|
<a @[event]="doSomething"> ... </a>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
## computed
|
||||||
|
|
||||||
|
#### 计算属性
|
||||||
|
|
||||||
|
- 计算属性是基于它们的响应式依赖进行缓存的
|
||||||
|
|
||||||
|
```js
|
||||||
|
<div id="example">
|
||||||
|
<p>Original message: "{{ message }}"</p>
|
||||||
|
<p>Computed reversed message: "{{ reversedMessage }}"</p>
|
||||||
|
</div>
|
||||||
|
var vm = new Vue({
|
||||||
|
el: '#example',
|
||||||
|
data: {
|
||||||
|
message: 'Hello'
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 计算属性的 getter
|
||||||
|
reversedMessage: function () {
|
||||||
|
// `this` 指向 vm 实例
|
||||||
|
return this.message.split('').reverse().join('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
<p>Reversed message: "{{ reversedMessage() }}"</p>
|
||||||
|
|
||||||
|
// 在组件中
|
||||||
|
methods: {
|
||||||
|
reversedMessage: function () {
|
||||||
|
return this.message.split('').reverse().join('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 监听属性
|
||||||
|
|
||||||
|
- 类似watch
|
||||||
|
|
||||||
|
```js
|
||||||
|
<div id="demo">{{ fullName }}</div>
|
||||||
|
// watch
|
||||||
|
var vm = new Vue({
|
||||||
|
el: '#demo',
|
||||||
|
data: {
|
||||||
|
firstName: 'Foo',
|
||||||
|
lastName: 'Bar',
|
||||||
|
fullName: 'Foo Bar'
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
firstName: function (val) {
|
||||||
|
this.fullName = val + ' ' + this.lastName
|
||||||
|
},
|
||||||
|
lastName: function (val) {
|
||||||
|
this.fullName = this.firstName + ' ' + val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
//
|
||||||
|
var vm = new Vue({
|
||||||
|
el: '#demo',
|
||||||
|
data: {
|
||||||
|
firstName: 'Foo',
|
||||||
|
lastName: 'Bar'
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
fullName: function () {
|
||||||
|
return this.firstName + ' ' + this.lastName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### set
|
||||||
|
|
||||||
|
```js
|
||||||
|
computed: {
|
||||||
|
fullName: {
|
||||||
|
// getter
|
||||||
|
get: function () {
|
||||||
|
return this.firstName + ' ' + this.lastName
|
||||||
|
},
|
||||||
|
// setter
|
||||||
|
set: function (newValue) {
|
||||||
|
var names = newValue.split(' ')
|
||||||
|
this.firstName = names[0]
|
||||||
|
this.lastName = names[names.length - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 现在再运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstName 和 vm.lastName 也会相应地被更新。
|
||||||
|
```
|
||||||
|
|
||||||
|
## 监听器
|
||||||
|
|
||||||
|
- 当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
|
||||||
|
- 在这个示例中,使用 `watch` 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
|
||||||
|
|
||||||
|
```js
|
||||||
|
<div id="watch-example">
|
||||||
|
<p>
|
||||||
|
Ask a yes/no question:
|
||||||
|
<input v-model="question">
|
||||||
|
</p>
|
||||||
|
<p>{{ answer }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
|
||||||
|
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var watchExampleVM = new Vue({
|
||||||
|
el: '#watch-example',
|
||||||
|
data: {
|
||||||
|
question: '',
|
||||||
|
answer: 'I cannot give you an answer until you ask a question!'
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 如果 `question` 发生改变,这个函数就会运行
|
||||||
|
question: function (newQuestion, oldQuestion) {
|
||||||
|
this.answer = 'Waiting for you to stop typing...'
|
||||||
|
this.debouncedGetAnswer()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created: function () {
|
||||||
|
// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
|
||||||
|
// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
|
||||||
|
// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
|
||||||
|
// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
|
||||||
|
// 请参考:https://lodash.com/docs#debounce
|
||||||
|
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getAnswer: function () {
|
||||||
|
if (this.question.indexOf('?') === -1) {
|
||||||
|
this.answer = 'Questions usually contain a question mark. ;-)'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.answer = 'Thinking...'
|
||||||
|
var vm = this
|
||||||
|
axios.get('https://yesno.wtf/api')
|
||||||
|
.then(function (response) {
|
||||||
|
vm.answer = _.capitalize(response.data.answer)
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
vm.answer = 'Error! Could not reach the API. ' + error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
### v-bind:class
|
||||||
|
|
||||||
|
#### 属性
|
||||||
|
|
||||||
|
- 我们可以传给 `v-bind:class` 一个对象,以动态地切换 class
|
||||||
|
|
||||||
|
```js
|
||||||
|
<div
|
||||||
|
class="static"
|
||||||
|
v-bind:class="{ active: isActive, 'text-danger': hasError }"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
data: {
|
||||||
|
isActive: true,
|
||||||
|
hasError: false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 对象
|
||||||
|
|
||||||
|
```js
|
||||||
|
<div class="static active"></div>
|
||||||
|
|
||||||
|
//绑定的数据对象不必内联定义在模板里:
|
||||||
|
<div v-bind:class="classObject"></div>
|
||||||
|
data: {
|
||||||
|
classObject: {
|
||||||
|
active: true,
|
||||||
|
'text-danger': false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data: {
|
||||||
|
isActive: true,
|
||||||
|
error: null
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
classObject: function () {
|
||||||
|
return {
|
||||||
|
active: this.isActive && !this.error,
|
||||||
|
'text-danger': this.error && this.error.type === 'fatal'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 数组
|
||||||
|
|
||||||
|
```js
|
||||||
|
<div v-bind:class="[activeClass, errorClass]"></div>
|
||||||
|
data: {
|
||||||
|
activeClass: 'active',
|
||||||
|
errorClass: 'text-danger'
|
||||||
|
}
|
||||||
|
<div class="active text-danger"></div>
|
||||||
|
|
||||||
|
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
|
||||||
|
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 用在组件上
|
||||||
|
|
||||||
|
组件中信息不会被覆盖而是追加
|
||||||
|
|
||||||
|
### 绑定内联样式 v-bind:style
|
||||||
|
|
||||||
|
- CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
|
||||||
|
<div v-bind:style="styleObject"></div>
|
||||||
|
<div v-bind:style="[baseStyles, overridingStyles]"></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
data: {
|
||||||
|
activeColor: 'red',
|
||||||
|
fontSize: 30
|
||||||
|
}
|
||||||
|
data: {
|
||||||
|
styleObject: {
|
||||||
|
color: 'red',
|
||||||
|
fontSize: '13px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
#### v-if
|
||||||
|
|
||||||
|
- 当 `v-if` 与 `v-for` 一起使用时,`v-for` 具有比 `v-if` 更高的优先级。不推荐两个一起使用
|
||||||
|
|
||||||
|
```html
|
||||||
|
<h1 v-if="awesome">Vue is awesome!</h1>
|
||||||
|
<h1 v-else>Oh no 😢</h1>
|
||||||
|
|
||||||
|
<template v-if="ok">
|
||||||
|
<h1>Title</h1>
|
||||||
|
<p>Paragraph 1</p>
|
||||||
|
<p>Paragraph 2</p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div v-if="Math.random() > 0.5">
|
||||||
|
Now you see me
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
Now you don't
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="type === 'A'">
|
||||||
|
A
|
||||||
|
</div>
|
||||||
|
<div v-else-if="type === 'B'">
|
||||||
|
B
|
||||||
|
</div>
|
||||||
|
<div v-else-if="type === 'C'">
|
||||||
|
C
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
Not A/B/C
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### key管理可复用元素
|
||||||
|
|
||||||
|
- 那么在上面的代码中切换 `loginType` 将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,`<input>` 不会被替换掉——仅仅是替换了它的 `placeholder`。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template v-if="loginType === 'username'">
|
||||||
|
<label>Username</label>
|
||||||
|
<input placeholder="Enter your username">
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<label>Email</label>
|
||||||
|
<input placeholder="Enter your email address">
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
- 这样也不总是符合实际需求,所以 Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 `key` attribute 即可
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template v-if="loginType === 'username'">
|
||||||
|
<label>Username</label>
|
||||||
|
<input placeholder="Enter your username" key="username-input">
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<label>Email</label>
|
||||||
|
<input placeholder="Enter your email address" key="email-input">
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### v-show
|
||||||
|
|
||||||
|
```html
|
||||||
|
<h1 v-show="ok">Hello!</h1>
|
||||||
|
```
|
||||||
|
|
||||||
|
- v-show` 不支持 `<template>` 元素,也不支持 `v-else
|
||||||
|
|
|
@ -0,0 +1,221 @@
|
||||||
|
#### v-for
|
||||||
|
|
||||||
|
```html
|
||||||
|
<ul id="example-1">
|
||||||
|
<li v-for="item in items" :key="item.message">
|
||||||
|
{{ item.message }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
var example1 = new Vue({
|
||||||
|
el: '#example-1',
|
||||||
|
data: {
|
||||||
|
items: [
|
||||||
|
{ message: 'Foo' },
|
||||||
|
{ message: 'Bar' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<ul id="example-2">
|
||||||
|
<li v-for="(item, index) in items">
|
||||||
|
{{ parentMessage }} - {{ index }} - {{ item.message }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
var example2 = new Vue({
|
||||||
|
el: '#example-2',
|
||||||
|
data: {
|
||||||
|
parentMessage: 'Parent',
|
||||||
|
items: [
|
||||||
|
{ message: 'Foo' },
|
||||||
|
{ message: 'Bar' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### v-for遍历一个对象的元素
|
||||||
|
|
||||||
|
```html
|
||||||
|
<ul id="v-for-object" class="demo">
|
||||||
|
<li v-for="value in object">
|
||||||
|
{{ value }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div v-for="(value, name) in object">
|
||||||
|
{{ name }}: {{ value }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-for="(value, name, index) in object">
|
||||||
|
{{ index }}. {{ name }}: {{ value }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-for="item in items" v-bind:key="item.id">
|
||||||
|
<!-- 内容 -->
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
new Vue({
|
||||||
|
el: '#v-for-object',
|
||||||
|
data: {
|
||||||
|
object: {
|
||||||
|
title: 'How to do lists in Vue',
|
||||||
|
author: 'Jane Doe',
|
||||||
|
publishedAt: '2016-04-10'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 显示过滤/排序后的结果
|
||||||
|
|
||||||
|
- 有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<li v-for="n in evenNumbers">{{ n }}</li>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
data: {
|
||||||
|
numbers: [ 1, 2, 3, 4, 5 ]
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
evenNumbers: function () {
|
||||||
|
return this.numbers.filter(function (number) {
|
||||||
|
return number % 2 === 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- 在计算属性不适用的情况下 (例如,在嵌套 `v-for` 循环中) 可以使用一个方法
|
||||||
|
|
||||||
|
```html
|
||||||
|
<ul v-for="set in sets">
|
||||||
|
<li v-for="n in even(set)">{{ n }}</li>
|
||||||
|
</ul>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
data: {
|
||||||
|
sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
even: function (numbers) {
|
||||||
|
return numbers.filter(function (number) {
|
||||||
|
return number % 2 === 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div>
|
||||||
|
<span v-for="n in 10">{{ n }} </span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<template v-for="item in items">
|
||||||
|
<li>{{ item.msg }}</li>
|
||||||
|
<li class="divider" role="presentation"></li>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### v-for,v-if 一同使用
|
||||||
|
|
||||||
|
- 当它们处于同一节点,`v-for` 的优先级比 `v-if` 更高,这意味着 `v-if` 将分别重复运行于每个 `v-for` 循环中。当你只想为*部分*项渲染节点时,这种优先级的机制会十分有用。
|
||||||
|
-
|
||||||
|
|
||||||
|
```html
|
||||||
|
<--代码将只渲染未完成的 todo-->
|
||||||
|
<li v-for="todo in todos" v-if="!todo.isComplete">
|
||||||
|
{{ todo }}
|
||||||
|
</li>
|
||||||
|
<ul v-if="todos.length">
|
||||||
|
<li v-for="todo in todos">
|
||||||
|
{{ todo }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p v-else>No todos left!</p>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### v-for在组件中
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="todo-list-example">
|
||||||
|
<form v-on:submit.prevent="addNewTodo">
|
||||||
|
<label for="new-todo">Add a todo</label>
|
||||||
|
<input
|
||||||
|
v-model="newTodoText"
|
||||||
|
id="new-todo"
|
||||||
|
placeholder="E.g. Feed the cat"
|
||||||
|
>
|
||||||
|
<button>Add</button>
|
||||||
|
</form>
|
||||||
|
<ul>
|
||||||
|
<li
|
||||||
|
is="todo-item"
|
||||||
|
v-for="(todo, index) in todos"
|
||||||
|
v-bind:key="todo.id"
|
||||||
|
v-bind:title="todo.title"
|
||||||
|
v-on:remove="todos.splice(index, 1)"
|
||||||
|
></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
Vue.component('todo-item', {
|
||||||
|
template: '\
|
||||||
|
<li>\
|
||||||
|
{{ title }}\
|
||||||
|
<button v-on:click="$emit(\'remove\')">Remove</button>\
|
||||||
|
</li>\
|
||||||
|
',
|
||||||
|
props: ['title']
|
||||||
|
})
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#todo-list-example',
|
||||||
|
data: {
|
||||||
|
newTodoText: '',
|
||||||
|
todos: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: 'Do the dishes',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: 'Take out the trash',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: 'Mow the lawn'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
nextTodoId: 4
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addNewTodo: function () {
|
||||||
|
this.todos.push({
|
||||||
|
id: this.nextTodoId++,
|
||||||
|
title: this.newTodoText
|
||||||
|
})
|
||||||
|
this.newTodoText = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
```html
|
||||||
|
<div id="example-1">
|
||||||
|
<button v-on:click="counter += 1">Add 1</button>
|
||||||
|
<p>The button above has been clicked {{ counter }} times.</p>
|
||||||
|
</div>
|
||||||
|
<div id="example-2">
|
||||||
|
<!-- `greet` 是在下面定义的方法名 -->
|
||||||
|
<button v-on:click="greet">Greet</button>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
var example1 = new Vue({
|
||||||
|
el: '#example-1',
|
||||||
|
data: {
|
||||||
|
counter: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
var example2 = new Vue({
|
||||||
|
el: '#example-2',
|
||||||
|
data: {
|
||||||
|
name: 'Vue.js'
|
||||||
|
},
|
||||||
|
// 在 `methods` 对象中定义方法
|
||||||
|
methods: {
|
||||||
|
greet: function (event) {
|
||||||
|
// `this` 在方法里指向当前 Vue 实例
|
||||||
|
alert('Hello ' + this.name + '!')
|
||||||
|
// `event` 是原生 DOM 事件
|
||||||
|
if (event) {
|
||||||
|
alert(event.target.tagName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 也可以用 JavaScript 直接调用方法
|
||||||
|
example2.greet() // => 'Hello Vue.js!'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 内联处理器中的方法调用
|
||||||
|
|
||||||
|
- 有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 `$event` 把它传入方法
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="example-3">
|
||||||
|
<button v-on:click="say('hi')">Say hi</button>
|
||||||
|
<button v-on:click="say('what')">Say what</button>
|
||||||
|
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
new Vue({
|
||||||
|
el: '#example-3',
|
||||||
|
methods: {
|
||||||
|
say: function (message) {
|
||||||
|
alert(message)
|
||||||
|
},
|
||||||
|
warn: function (message, event) {
|
||||||
|
// 现在我们可以访问原生事件对象
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
alert(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### [事件修饰符](https://cn.vuejs.org/v2/guide/events.html#事件修饰符)
|
||||||
|
|
||||||
|
- 键盘按键处理
|
||||||
|
- 鼠标按键处理
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- 阻止单击事件继续传播 -->
|
||||||
|
<a v-on:click.stop="doThis"></a>
|
||||||
|
|
||||||
|
<!-- 提交事件不再重载页面 -->
|
||||||
|
<form v-on:submit.prevent="onSubmit"></form>
|
||||||
|
|
||||||
|
<!-- 修饰符可以串联 -->
|
||||||
|
<a v-on:click.stop.prevent="doThat"></a>
|
||||||
|
|
||||||
|
<!-- 只有修饰符 -->
|
||||||
|
<form v-on:submit.prevent></form>
|
||||||
|
|
||||||
|
<!-- 添加事件监听器时使用事件捕获模式 -->
|
||||||
|
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
|
||||||
|
<div v-on:click.capture="doThis">...</div>
|
||||||
|
|
||||||
|
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
|
||||||
|
<!-- 即事件不是从内部元素触发的 -->
|
||||||
|
<div v-on:click.self="doThat">...</div>
|
||||||
|
|
||||||
|
<!-- 点击事件将只会触发一次 -->
|
||||||
|
<a v-on:click.once="doThis"></a>
|
||||||
|
|
||||||
|
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
|
||||||
|
<!-- 而不会等待 `onScroll` 完成 -->
|
||||||
|
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
|
||||||
|
<div v-on:scroll.passive="onScroll">...</div>
|
||||||
|
|
||||||
|
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
|
||||||
|
<input v-on:keyup.enter="submit">
|
||||||
|
|
||||||
|
<input v-on:keyup.page-down="onPageDown">
|
||||||
|
|
||||||
|
<input v-on:keyup.13="submit">
|
||||||
|
|
||||||
|
// 可以使用 `v-on:keyup.f1`
|
||||||
|
Vue.config.keyCodes.f1 = 112
|
||||||
|
<!-- Alt + C -->
|
||||||
|
<input v-on:keyup.alt.67="clear">
|
||||||
|
|
||||||
|
<!-- Ctrl + Click -->
|
||||||
|
<div v-on:click.ctrl="doSomething">Do something</div>
|
||||||
|
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
## v-model
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="example-6">
|
||||||
|
<select v-model="selected">
|
||||||
|
<option v-for="option in options" v-bind:value="option.value">
|
||||||
|
{{ option.text }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<span>Selected: {{ selected }}</span>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
new Vue({
|
||||||
|
el: 'example-6',
|
||||||
|
data: {
|
||||||
|
selected: 'A',
|
||||||
|
options: [
|
||||||
|
{ text: 'One', value: 'A' },
|
||||||
|
{ text: 'Two', value: 'B' },
|
||||||
|
{ text: 'Three', value: 'C' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
- 因为组件是可复用的 Vue 实例,所以它们与 `new Vue` 接收相同的选项,例如 `data`、`computed`、`watch`、`methods` 以及生命周期钩子等。仅有的例外是像 `el` 这样根实例特有的选项。
|
||||||
|
- 一个组件的 `data` 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝
|
||||||
|
- 通过prop向组件传递数据,`v-on` 监听子组件实例的任意事件
|
||||||
|
- [从一个 API 获取博文列表](https://codesandbox.io/s/github/vuejs/vuejs.org/tree/master/src/v2/examples/vue-20-component-blog-post-example)
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 定义一个名为 button-counter 的新组件
|
||||||
|
Vue.component('button-counter', {
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
count: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
|
||||||
|
})
|
||||||
|
|
||||||
|
Vue.component('blog-post', {
|
||||||
|
props: ['title'],
|
||||||
|
template: '<h3>{{ title }}</h3>'
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="components-demo">
|
||||||
|
<button-counter></button-counter>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<blog-post title="My journey with Vue"></blog-post>
|
||||||
|
<blog-post title="Blogging with Vue"></blog-post>
|
||||||
|
<blog-post title="Why Vue is so fun"></blog-post>
|
||||||
|
|
||||||
|
<blog-post
|
||||||
|
v-for="post in posts"
|
||||||
|
v-bind:key="post.id"
|
||||||
|
v-bind:title="post.title"
|
||||||
|
></blog-post>
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
new Vue({ el: '#components-demo' })
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#blog-post-demo',
|
||||||
|
data: {
|
||||||
|
posts: [
|
||||||
|
{ id: 1, title: 'My journey with Vue' },
|
||||||
|
{ id: 2, title: 'Blogging with Vue' },
|
||||||
|
{ id: 3, title: 'Why Vue is so fun' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## [动态组件](https://cn.vuejs.org/v2/guide/components.html#动态组件)
|
||||||
|
|
||||||
|
https://codesandbox.io/s/github/vuejs/vuejs.org/tree/master/src/v2/examples/vue-20-dynamic-components
|
|
@ -1,4 +1,4 @@
|
||||||
目录查看
|
### 目录查看
|
||||||
|
|
||||||
1. node_modules:安装依赖打包
|
1. node_modules:安装依赖打包
|
||||||
2. public:图片文件,index.html
|
2. public:图片文件,index.html
|
||||||
|
@ -34,3 +34,76 @@
|
||||||
17. vue.config.js:
|
17. vue.config.js:
|
||||||
|
|
||||||
vue-cli-service serve
|
vue-cli-service serve
|
||||||
|
|
||||||
|
### 总结
|
||||||
|
|
||||||
|
当配置baseURL时,代理不生效。
|
||||||
|
|
||||||
|
```js
|
||||||
|
const request = axios.create({
|
||||||
|
timeout: 30000, // 请求超时时间
|
||||||
|
baseURL: process.env.VUE_APP_URL,
|
||||||
|
withCredentials: true
|
||||||
|
});
|
||||||
|
|
||||||
|
proxy: {
|
||||||
|
'/': { // 代理api
|
||||||
|
target: 'http://localhost:8085', // 服务器api地址
|
||||||
|
changeOrigin: true//, // 是否跨域
|
||||||
|
// pathRewrite: {
|
||||||
|
// '^/': 'http://qiankun.bj-fanuc.com.cn/finance-admin/charts/selectChartDataByPageModel' // 路径重写
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 启动跟踪
|
||||||
|
|
||||||
|
```js
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
文件:package.json
|
||||||
|
|
||||||
|
```json
|
||||||
|
"dev": "webpack-dev-server --inline --progress --module-bind production --config build/webpack.dev.conf.js "
|
||||||
|
```
|
||||||
|
|
||||||
|
文件:build/webpack.dev.conf.js
|
||||||
|
|
||||||
|
```js
|
||||||
|
// these devServer options should be customized in /config/index.js
|
||||||
|
devServer: {
|
||||||
|
clientLogLevel: 'warning',
|
||||||
|
historyApiFallback: {
|
||||||
|
rewrites: [
|
||||||
|
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
hot: true,
|
||||||
|
contentBase: false, // since we use CopyWebpackPlugin.
|
||||||
|
compress: true,
|
||||||
|
host: HOST || config.dev.host,
|
||||||
|
port: PORT || config.dev.port,
|
||||||
|
open: config.dev.autoOpenBrowser,
|
||||||
|
overlay: config.dev.errorOverlay
|
||||||
|
? { warnings: false, errors: true }
|
||||||
|
: false,
|
||||||
|
publicPath: config.dev.assetsPublicPath,
|
||||||
|
proxy: config.dev.proxyTable,
|
||||||
|
quiet: true, // necessary for FriendlyErrorsPlugin
|
||||||
|
watchOptions: {
|
||||||
|
poll: config.dev.poll,
|
||||||
|
},
|
||||||
|
proxy: {
|
||||||
|
'/*': { // 代理api
|
||||||
|
target: 'http://localhost8080/', // 服务器api地址
|
||||||
|
changeOrigin: true, // 是否跨域
|
||||||
|
pathRewrite: {
|
||||||
|
'^/*': 'http://localhost:8081/' // 路径重写
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 49 KiB |
|
@ -0,0 +1,98 @@
|
||||||
|
## 基本参数
|
||||||
|
|
||||||
|
[基本参数说明](https://webpack.docschina.org/concepts)
|
||||||
|
|
||||||
|
1. 入口(entry)
|
||||||
|
2. 输出(output)
|
||||||
|
3. loader
|
||||||
|
4. 插件(plugin)
|
||||||
|
5. 模式(mode)
|
||||||
|
6. 浏览器兼容性(browser compatibility)
|
||||||
|
7. 环境(environment)
|
||||||
|
|
||||||
|
## 默认配置
|
||||||
|
|
||||||
|
1. 入口起点为 `src/index.js`
|
||||||
|
2. 然后会在 `dist/main.js` 输出结果
|
||||||
|
3. 并且在生产环境开启压缩和优化
|
||||||
|
4. 通常你的项目还需要继续扩展此能力,为此你可以在项目根目录下创建一个 `webpack.config.js` 文件,然后 webpack 会自动使用它。
|
||||||
|
|
||||||
|
[webpack.config.js配置](https://webpack.docschina.org/configuration)
|
||||||
|
|
||||||
|
**“webpack 配置的可扩展”** 是指,这些配置可以重复使用,并且可以与其他配置组合使用。这是一种流行的技术,用于将关注点从环境(environment)、构建目标(build target)、运行时(runtime)中分离。然后使用专门的工具(如 [webpack-merge](https://github.com/survivejs/webpack-merge))将它们合并起来。
|
||||||
|
|
||||||
|
- 使用 JavaScript 控制流表达式,例如 `?:` 操作符
|
||||||
|
- 精心编写的 **模块** 提供了可靠的抽象和封装界限,使得应用程序中每个模块都具备了条理清晰的设计和明确的目的。
|
||||||
|
- 应保证 loader 的先后顺序:[`'style-loader'`](https://webpack.docschina.org/loaders/style-loader) 在前,而 [`'css-loader'`](https://webpack.docschina.org/loaders/css-loader) 在后
|
||||||
|
|
||||||
|
## 基础文件
|
||||||
|
|
||||||
|
1. index.html是主入口
|
||||||
|
2. app.js是我们写的模块,并依据CommonJS规范导出这个模块
|
||||||
|
3. main.js其实是一个组件,它的目的是将我们写的一些代码模块返回并插入到页面中
|
||||||
|
|
||||||
|
不兼容问题升级
|
||||||
|
|
||||||
|
```js
|
||||||
|
npm i -D html-webpack-plugin@webpack-contrib/html-webpack-plugin
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
临时删除一些错误包
|
||||||
|
|
||||||
|
```
|
||||||
|
"eslint-loader": "^2.0.0",
|
||||||
|
"element-ui": "^2.15.7",
|
||||||
|
"less-loader": "6.0.0",
|
||||||
|
"jest": "^27.4.5",
|
||||||
|
"jest-serializer-vue": "^0.3.0",
|
||||||
|
"babel-jest": "^27.4.5",
|
||||||
|
"vue-jest": "^1.0.2",
|
||||||
|
"friendly-errors-webpack-plugin": "2.0.0-beta.2",
|
||||||
|
"uglifyjs-webpack-plugin": "2.2.0",
|
||||||
|
"babel-plugin-transform-runtime": "^7.14.0",
|
||||||
|
"@babel/core": "^7.12.3",
|
||||||
|
"@babel/plugin-transform-runtime": "7.12.13",
|
||||||
|
"@babel/preset-env": "^7.16.7",
|
||||||
|
"babel-eslint": "^10.0.1",
|
||||||
|
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||||
|
"babel-plugin-dynamic-import-node": "^1.2.0",
|
||||||
|
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||||
|
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
|
||||||
|
"babel-plugin-transform-vue-jsx": "4.0.1",
|
||||||
|
"babel-preset-env": "^1.3.2",
|
||||||
|
"babel-preset-stage-2": "^6.22.0",
|
||||||
|
"babel-register": "^6.22.0",
|
||||||
|
|
||||||
|
"@babel/preset-env":"7.16.7"
|
||||||
|
"babel-plugin-react-intl": "^8.2.15",
|
||||||
|
|
||||||
|
|
||||||
|
npm instal babel-preset-env
|
||||||
|
npm install babel-preset-stage-2
|
||||||
|
|
||||||
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
|
"babel-plugin-transform-vue-jsx": "^4.0.1",
|
||||||
|
"babel-preset-env": "^1.7.0",
|
||||||
|
"babel-preset-stage-2": "^6.24.1",
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------
|
||||||
|
"@babel/core": "^7.16.7",
|
||||||
|
"@babel/preset-env": "^7.16.7",
|
||||||
|
"babel-loader": "^8.2.3",
|
||||||
|
"babel-preset-stage-2": "7.0.0-beta.3",
|
||||||
|
"babel-runtime": "6.26.0",
|
||||||
|
|
||||||
|
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||||
|
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||||
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
|
"babel-plugin-transform-vue-jsx": "^3.7.0",
|
||||||
|
"babel-preset-env": "^1.7.0",
|
||||||
|
"@babel/preset-stage-2": "^7.8.3",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TypeError: src/main.js: this.setDynamic is not a function
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
组件类似与java中的类(对象)。
|
||||||
|
|
||||||
|
#### 全局组件
|
||||||
|
|
||||||
|
```js
|
||||||
|
Vue.component('component-a', { /* ... */ })
|
||||||
|
Vue.component('component-b', { /* ... */ })
|
||||||
|
Vue.component('component-c', { /* ... */ })
|
||||||
|
|
||||||
|
new Vue({ el: '#app' })
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="app">
|
||||||
|
<component-a></component-a>
|
||||||
|
<component-b></component-b>
|
||||||
|
<component-c></component-c>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 局部组件
|
||||||
|
|
||||||
|
```js
|
||||||
|
var ComponentA = { /* ... */ }
|
||||||
|
var ComponentB = { /* ... */ }
|
||||||
|
var ComponentC = { /* ... */ }
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
components: {
|
||||||
|
'component-a': ComponentA,
|
||||||
|
'component-b': ComponentB
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
|
@ -20,3 +20,4 @@
|
||||||
18. ~~解决方案文档~~
|
18. ~~解决方案文档~~
|
||||||
19. 修改接口确保之前逻辑不变
|
19. 修改接口确保之前逻辑不变
|
||||||
19. EntityGraph多看源码,注释下同级别有类似注释。
|
19. EntityGraph多看源码,注释下同级别有类似注释。
|
||||||
|
19. 用心做好每件事,每个人每件事,都值得被认真对待。
|