add:Vue 2.x(生命周期函数)
This commit is contained in:
parent
712ee55dd6
commit
c616642834
@ -1,5 +1,126 @@
|
||||
|
||||
|
||||
|
||||
|
||||
## 常见操作
|
||||
|
||||
### 配置用户信息
|
||||
|
||||
```
|
||||
git config --global user.name "smyhvae"
|
||||
|
||||
git config --global user.email "smyhvae@163.com"
|
||||
```
|
||||
|
||||
|
||||
## 分支的合并
|
||||
|
||||
|
||||
### 场景:基于master分支的代码,开发一个新的特性
|
||||
|
||||
如果你直接在master分支上开发这个新特性,是不好的,万一你在开发`特性1`的时候,领导突然又要叫你去开发`特性2`,就不好处理了。难道开发的两个特性都提交到master?一会儿提交特性1的commit,一会儿提交特性2的commit?这会导致commit记录很混乱。
|
||||
|
||||
所以,我给你的建议做法是:给每个特性都单独建一个的新的分支。
|
||||
|
||||
比如说,我专门给`特性1`建一个分支`feature_item_recommend`。具体做法如下:
|
||||
|
||||
(1)基于master分支,创建一个新的分支,起名为`feature_item_recommend`:
|
||||
|
||||
```
|
||||
$ git checkout -b feature_item_recommend
|
||||
|
||||
Switched to a new branch 'feature_item_recommend'
|
||||
```
|
||||
|
||||
上面这行命令,相当于:
|
||||
|
||||
|
||||
```bash
|
||||
$ git branch feature_item_recommend // 创建新的分支
|
||||
|
||||
$ git checkout feature_item_recommend //切换到新的分支
|
||||
```
|
||||
|
||||
|
||||
(2)在新的分支`feature_item_recommend`上,完成开发工作,并 commit 、push。
|
||||
|
||||
(3)将分支`feature_item_recommend`上的开发进度**合并**到master分支:
|
||||
|
||||
```bash
|
||||
$ git checkout master //切换到master分支
|
||||
|
||||
$ git merge feature_item_recommend //将分支 feature_item_recommend 的开发进度合并到 master 分支
|
||||
|
||||
```
|
||||
|
||||
|
||||
合并之后,`master`分支和`feature_item_recommend`分支会指向同一个位置。
|
||||
|
||||
|
||||
(3)删除分支`feature_item_recommend`:
|
||||
|
||||
> 既然 特性1 开发完了,也放心地提交到master了,那我们就可以将这个分支删除了。
|
||||
|
||||
```
|
||||
git branch -d feature_item_recommend
|
||||
```
|
||||
|
||||
注意,我们当前是处于`master`分支的位置,来删除`feature_item_recommend`分支。如果当前是处于`feature_item_recommend`分支,是没办法删除它自己的。
|
||||
|
||||
同理,当我转身去开发`特性2`的时候,也是采用同样的步骤。
|
||||
|
||||
|
||||
### 合并分支时,如果存在分叉
|
||||
|
||||
|
||||
20180610_1650.png
|
||||
|
||||
比如说上面这张图中,最早的时候,master分支是位于`C2`节点。我基于`C2`节点,new出一个新的分支`iss53`,我在`iss53`上提交了好几个commit。
|
||||
|
||||
现在,我准备把`iss53`上的几个commit合并到master上,此时发现,master分支已经前进到C4了。那该怎么合并呢?
|
||||
|
||||
合并的命令仍然是:
|
||||
|
||||
```bash
|
||||
$ git checkout master
|
||||
|
||||
$ git merge iss53
|
||||
```
|
||||
|
||||
**解释**:
|
||||
|
||||
这次合并的实现,并不同于简单的并入方式。这一次,我的开发历史是从更早的地方开始分叉的。
|
||||
|
||||
由于当前 master 分支所指向的commit (C4)并非想要并入分支(iss53)的直接祖先,Git 不得不进行一些处理。就此例而言,Git 会用两个分支的末端(C4 和C5)和它们的共同祖先(C2)进行一次简单的三方合并计算。
|
||||
|
||||
Git 没有简单地把分支指针右移,而是对三方合并的结果作一新的快照,并自动创建一个指向它的commit(C6)(如下图所示)。我们把这个特殊的commit 称作合并提交(mergecommit),因为它的祖先不止一个。
|
||||
|
||||
值得一提的是Git 可以自己裁决哪个共同祖先才是最佳合并基础;这和CVS 或Subversion(1.5 以后的版本)不同,它们需要开发者手工指定合并基础。所以此特性让Git 的合并操作比其他系统都要简单不少。
|
||||
|
||||
20180610_1710.png
|
||||
|
||||
### 解决合并时发生的冲突
|
||||
|
||||
20180610_1740.png
|
||||
|
||||
如果 feature1和feature2修改的是同一个文件中**代码的同一个位置**,那么,把feature1合并到feature2时,就会产生冲突。这个冲突需要人工解决。步骤如下:
|
||||
|
||||
(1)手动修改文件:手动修改冲突的那个文件,决定到底要用哪个分支的代码。
|
||||
|
||||
(2)git add:解决好冲突后,输入`git status`,会提示`Unmerged paths`。这个时候,输入`git add`即可,表示:**修改冲突成功,加入暂存区**。
|
||||
|
||||
(3)git commit 提交。
|
||||
|
||||
然后,我们可以继续把 feature1 分支合并到 master分支,最后删除feature1、feature2。
|
||||
|
||||
**注意**:两个分支的同一个文件的不同地方合并时,git会自动合并,不会产生冲突。
|
||||
|
||||
比如分支feture1对index.html原来的第二行之前加入了一段代码。
|
||||
分支feature2对index.html在原来的最后一行的后面加入了一段代码。
|
||||
这个时候在对两个分支合并,git不会产生冲突,因为两个分支是修改同一文件的不同位置。
|
||||
git自动合并成功。不管是git自动合并成功,还是在人工解决冲突下合并成功,提交之前,都要对代码进行测试。
|
||||
|
||||
|
||||
## 日常操作积累
|
||||
|
||||
|
||||
@ -7,7 +128,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
### 将 `branch1`的某个`commit1`合并到`branch2`当中
|
||||
|
||||
切换到branch2中,然后执行如下命令:
|
||||
@ -19,6 +139,9 @@ git cherry-pick commit1
|
||||
|
||||
|
||||
|
||||
## 推荐书籍
|
||||
|
||||
- 《pro.git中文版》
|
||||
|
||||
|
||||
|
||||
@ -30,3 +153,5 @@ git cherry-pick commit1
|
||||
- [聊下git pull --rebase](https://www.cnblogs.com/wangiqngpei557/p/6056624.html)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -50,12 +50,14 @@ PS:如果浏览器不支持,则这句话只解析为一条简单的语句,
|
||||
|
||||
## 严格模式和普通模式的区别
|
||||
|
||||
### 1、全局变量显式声明
|
||||
> 下面列举几条严格模式的内容。
|
||||
|
||||
### 全局变量显式声明
|
||||
|
||||
在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。
|
||||
|
||||
|
||||
### 2、禁止this关键字指向全局对象:
|
||||
### 禁止this关键字指向全局对象:
|
||||
|
||||
```javascript
|
||||
var foo = function () {
|
||||
@ -66,16 +68,15 @@ PS:如果浏览器不支持,则这句话只解析为一条简单的语句,
|
||||
```
|
||||
上方代码中,普通模式打印的是window。严格模式下打印的是undefined。
|
||||
|
||||
### 3、创设eval作用域
|
||||
### 创设eval作用域
|
||||
|
||||
|
||||
|
||||
### 2、禁止使用with语句
|
||||
### 禁止使用with语句
|
||||
|
||||
因为with语句无法在编译时就确定,属性到底归属哪个对象。
|
||||
|
||||
|
||||
|
||||
### 构造函数必须通过new实例化对象
|
||||
|
||||
构造函数必须通过new实例化对象,否则报错。因为this为undefined,此时无法设置属性。
|
||||
@ -94,12 +95,12 @@ PS:如果浏览器不支持,则这句话只解析为一条简单的语句,
|
||||
上方代码中,如果在严格模式下,则会报错。
|
||||
|
||||
|
||||
### 5、为了让代码更安全,禁止函数内部遍历调用栈
|
||||
### 为了让代码更安全,禁止函数内部遍历调用栈
|
||||
|
||||
### 6、严格模式下无法删除变量
|
||||
### 严格模式下无法删除变量
|
||||
|
||||
|
||||
### 7~10 属性相关
|
||||
### 属性相关
|
||||
|
||||
普通模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败。严格模式下,将报错。
|
||||
|
||||
|
@ -527,7 +527,7 @@ console.log(fn1(1, 2)); //输出结果:3
|
||||
|
||||
如果我把第一个参数改一下,改成:
|
||||
|
||||
20180312_2017.png
|
||||
![](http://img.smyhvae.com/20180312_2017.png)
|
||||
|
||||
此时打印结果是:`vae smyh`。
|
||||
|
||||
|
@ -209,12 +209,9 @@ Symbol是函数,但并不是构造函数。创建一个Symbol数据类型:
|
||||
console.log(mySymbol); //打印结果:Symbol()
|
||||
```
|
||||
|
||||
|
||||
打印结果:
|
||||
|
||||
20180317_1134.png
|
||||
|
||||
|
||||
![](http://img.smyhvae.com/20180317_1134.png)
|
||||
|
||||
下面来讲一下Symbol的使用。
|
||||
|
||||
@ -234,10 +231,9 @@ Symbol是函数,但并不是构造函数。创建一个Symbol数据类型:
|
||||
console.log(obj);
|
||||
```
|
||||
|
||||
|
||||
上面的代码中,我们尝试给obj添加一个Symbol类型的属性值,但是添加的时候,不能采用`.`这个符号,而是应该用`属性选择器`的方式。打印结果:
|
||||
|
||||
20180317_1145.png
|
||||
![](http://img.smyhvae.com/20180317_1134.png)
|
||||
|
||||
现在我们用for in尝试对上面的obj进行遍历:
|
||||
|
||||
@ -261,11 +257,10 @@ Symbol是函数,但并不是构造函数。创建一个Symbol数据类型:
|
||||
|
||||
打印结果:
|
||||
|
||||
20180317_1817.png
|
||||
![](http://img.smyhvae.com/20180317_1134.png)
|
||||
|
||||
从打印结果中可以看到:for in、for of 遍历时不会遍历Symbol属性。
|
||||
|
||||
|
||||
### 创建Symbol属性值时,传参作为标识
|
||||
|
||||
如果我通过 Symbol()函数创建了两个值,这两个值是不一样的:
|
||||
@ -279,7 +274,7 @@ Symbol是函数,但并不是构造函数。创建一个Symbol数据类型:
|
||||
console.log(mySymbol2); //打印结果:Symbol()
|
||||
```
|
||||
|
||||
20180317_1733.png
|
||||
![](http://img.smyhvae.com/20180317_1134.png)
|
||||
|
||||
上面代码中,倒数第三行的打印结果也就表明了,二者的值确实是不相等的。
|
||||
|
||||
@ -288,7 +283,6 @@ Symbol是函数,但并不是构造函数。创建一个Symbol数据类型:
|
||||
既然Symbol()是函数,函数就可以传入参数,我们可以通过参数的不同来作为**标识**。比如:
|
||||
|
||||
|
||||
|
||||
```javascript
|
||||
//在括号里加入参数,来标识不同的Symbol
|
||||
let mySymbol1 = Symbol('one');
|
||||
@ -302,21 +296,18 @@ Symbol是函数,但并不是构造函数。创建一个Symbol数据类型:
|
||||
|
||||
打印结果:
|
||||
|
||||
20180317_1739.png
|
||||
![](http://img.smyhvae.com/20180317_1134.png)
|
||||
|
||||
### 定义常量
|
||||
|
||||
Symbol 可以用来定义常量:
|
||||
|
||||
|
||||
|
||||
|
||||
```javascript
|
||||
const MY_NAME = Symbol('my_name');
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 内置的 Symbol 值
|
||||
|
||||
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。
|
||||
@ -326,7 +317,6 @@ Symbol 可以用来定义常量:
|
||||
对象的`Symbol.iterator`属性,指向该对象的默认遍历器方法。
|
||||
|
||||
|
||||
|
||||
## async函数(异步函数)
|
||||
|
||||
### 概述
|
||||
|
@ -35,7 +35,7 @@ ES6中的字符串扩展,用得少,而且逻辑相对简单。如下:
|
||||
|
||||
打印结果:
|
||||
|
||||
20180402_1050.png
|
||||
![](http://img.smyhvae.com/20180402_1050.png)
|
||||
|
||||
## 数值的扩展
|
||||
|
||||
@ -115,11 +115,11 @@ ES6中的字符串扩展,用得少,而且逻辑相对简单。如下:
|
||||
|
||||
上面的布局中,有三个button标签,我们通过`getElementsByTagName`获取到的`btnArray`实际上是**伪数组**,并不是真实的数组:
|
||||
|
||||
20180402_1116.png
|
||||
![](http://img.smyhvae.com/20180402_1116.png)
|
||||
|
||||
既然`btnArray`是伪数组,它就不能使用数组的一般方法,否则会报错:
|
||||
|
||||
20180402_1121.png
|
||||
![](http://img.smyhvae.com/20180402_1121.png)
|
||||
|
||||
解决办法:采用`Array.from`方法将`btnArray`这个伪数组转换为真数组即可:
|
||||
|
||||
@ -129,7 +129,7 @@ ES6中的字符串扩展,用得少,而且逻辑相对简单。如下:
|
||||
|
||||
然后就可以使用数组的一般方法了:
|
||||
|
||||
20180402_1125.png
|
||||
![](http://img.smyhvae.com/20180402_1125.png)
|
||||
|
||||
### 扩展2
|
||||
|
||||
@ -259,7 +259,7 @@ ES6中的字符串扩展,用得少,而且逻辑相对简单。如下:
|
||||
|
||||
打印结果:
|
||||
|
||||
20180404_2240.png
|
||||
![](http://img.smyhvae.com/20180404_2240.png)
|
||||
|
||||
上图显示,成功将obj1和obj2的属性复制给了obj3。
|
||||
|
||||
@ -280,7 +280,7 @@ ES6中的字符串扩展,用得少,而且逻辑相对简单。如下:
|
||||
|
||||
打印结果:
|
||||
|
||||
20180404_2251.png
|
||||
![](http://img.smyhvae.com/20180404_2251.png)
|
||||
|
||||
上方代码中,obj2本身是没有属性的,但是通过`__proto__`属性和obj1产生关联,于是就可以获得obj1里的属性。
|
||||
|
||||
@ -307,13 +307,6 @@ ES6中的字符串扩展,用得少,而且逻辑相对简单。如下:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -7,36 +7,45 @@
|
||||
|
||||
|
||||
|
||||
[vue实例的生命周期](https://cn.vuejs.org/v2/guide/instance.html#实例生命周期):从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期。
|
||||
- [vue实例的生命周期](https://cn.vuejs.org/v2/guide/instance.html#实例生命周期):从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期。
|
||||
|
||||
|
||||
[生命周期钩子](https://cn.vuejs.org/v2/api/#选项-生命周期钩子):就是生命周期事件的别名而已。
|
||||
- [生命周期钩子](https://cn.vuejs.org/v2/api/#选项-生命周期钩子):就是生命周期事件的别名而已。
|
||||
|
||||
生命周期钩子 = 生命周期函数 = 生命周期事件。
|
||||
|
||||
|
||||
### 主要的生命周期函数分类
|
||||
|
||||
|
||||
创建期间的生命周期函数:
|
||||
|
||||
|
||||
+ beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
|
||||
+ created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
|
||||
+ beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
|
||||
+ mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
|
||||
- 运行期间的生命周期函数:
|
||||
+ beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
|
||||
+ updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
|
||||
- 销毁期间的生命周期函数:
|
||||
+ beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
|
||||
+ destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
|
||||
|
||||
|
||||
## Vue 2.0的生命周期函数
|
||||
### 生命周期函数的主要分类
|
||||
|
||||
![](http://img.smyhvae.com/20180422_1650.png)
|
||||
|
||||
1、创建期间的生命周期函数:
|
||||
|
||||
- beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
|
||||
|
||||
- created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
|
||||
|
||||
- beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
|
||||
|
||||
- mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
|
||||
|
||||
2、运行期间的生命周期函数:
|
||||
|
||||
- beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
|
||||
|
||||
- updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了。
|
||||
|
||||
|
||||
3、销毁期间的生命周期函数:
|
||||
|
||||
- beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
|
||||
|
||||
- destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
|
||||
|
||||
|
||||
举例1:创建期间的生命周期函数
|
||||
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@ -59,20 +68,29 @@
|
||||
data: {
|
||||
msg: 'hello vuejs'
|
||||
},
|
||||
// 这是第1个生命周期函数,表示实例完全被创建出来之前,会执行它
|
||||
beforeCreate: function () {
|
||||
console.log('1.0 beforeCreate', this.msg);
|
||||
}
|
||||
,
|
||||
console.log('01 beforeCreate', this.msg);
|
||||
//注意:在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化
|
||||
},
|
||||
|
||||
// 这是第2个生命周期函数
|
||||
created: function () {
|
||||
console.log('2.0 created', this.msg);
|
||||
}
|
||||
,
|
||||
console.log('02 created', this.msg);
|
||||
//注意:如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作
|
||||
},
|
||||
|
||||
// 这是第3个生命周期函数,表示 模板已经在内存中编辑完成了,但是尚未把模板渲染到页面中
|
||||
beforeMount: function () {
|
||||
console.log('3.0 beforeMount', this.msg);
|
||||
}
|
||||
,
|
||||
console.log('03 beforeMount', this.msg);
|
||||
// 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串
|
||||
},
|
||||
|
||||
// 这是第4个生命周期函数,表示,内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
|
||||
mounted: function () {
|
||||
console.log('4.0 mounted', this.msg);
|
||||
console.log('04 mounted', this.msg);
|
||||
// 注意: mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了
|
||||
// 此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动
|
||||
}
|
||||
});
|
||||
|
||||
@ -83,6 +101,69 @@
|
||||
|
||||
打印结果:
|
||||
|
||||
![](http://img.smyhvae.com/20180420_2302.png)
|
||||
20180610_1500.png
|
||||
|
||||
|
||||
举例2:运行期间的生命周期函数
|
||||
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<script src="vue2.5.16.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--这个div区域就是MVVM中的 View-->
|
||||
<div id="app">
|
||||
<input type="button" value="修改flag" @click="myMethod">
|
||||
<h3 id="h3">{{ flag }}</h3>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
msg: 'hello vue',
|
||||
flag: false
|
||||
},
|
||||
|
||||
methods: {
|
||||
myMethod: function () {
|
||||
this.flag = true;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 接下来的是运行中的两个事件
|
||||
// 这时候,我们的界面还没有被更新【但是,数据被更新了吗? 数据肯定被更新了】
|
||||
beforeUpdate() {
|
||||
console.log('-------------05 beforeUpdate', this.msg);
|
||||
|
||||
// 结论:当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面尚未和 最新的数据保持同步
|
||||
console.log('界面上DOM元素显示的内容:' + document.getElementById('h3').innerText)
|
||||
console.log('data 中的 msg 数据:' + this.flag)
|
||||
},
|
||||
updated() {
|
||||
console.log('-------------06 updated', this.msg);
|
||||
|
||||
// 结论:updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
|
||||
console.log('界面上DOM元素显示的内容:' + document.getElementById('h3').innerText)
|
||||
console.log('data 中的 msg 数据:' + this.flag)
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
|
||||
当我们点击按钮后,运行效果是:
|
||||
|
||||
20180610_1528.png
|
||||
|
Loading…
Reference in New Issue
Block a user