add:Vue 2.x(生命周期函数)

This commit is contained in:
qianguyihao 2018-06-11 21:11:23 +08:00
parent 712ee55dd6
commit c616642834
6 changed files with 260 additions and 70 deletions

View File

@ -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 没有简单地把分支指针右移而是对三方合并的结果作一新的快照并自动创建一个指向它的commitC6如下图所示。我们把这个特殊的commit 称作合并提交mergecommit因为它的祖先不止一个。
值得一提的是Git 可以自己裁决哪个共同祖先才是最佳合并基础这和CVS 或Subversion1.5 以后的版本不同它们需要开发者手工指定合并基础。所以此特性让Git 的合并操作比其他系统都要简单不少。
20180610_1710.png
### 解决合并时发生的冲突
20180610_1740.png
如果 feature1和feature2修改的是同一个文件中**代码的同一个位置**那么把feature1合并到feature2时就会产生冲突。这个冲突需要人工解决。步骤如下
1手动修改文件手动修改冲突的那个文件决定到底要用哪个分支的代码。
2git add解决好冲突后输入`git status`,会提示`Unmerged paths`。这个时候,输入`git add`即可,表示:**修改冲突成功,加入暂存区**。
3git commit 提交。
然后,我们可以继续把 feature1 分支合并到 master分支最后删除feature1、feature2。
**注意**两个分支的同一个文件的不同地方合并时git会自动合并不会产生冲突。
比如分支feture1对index.html原来的第二行之前加入了一段代码。
分支feature2对index.html在原来的最后一行的后面加入了一段代码。
这个时候在对两个分支合并git不会产生冲突因为两个分支是修改同一文件的不同位置。
git自动合并成功。不管是git自动合并成功还是在人工解决冲突下合并成功提交之前都要对代码进行测试。
## 日常操作积累 ## 日常操作积累
@ -7,7 +128,6 @@
### 将 `branch1`的某个`commit1`合并到`branch2`当中 ### 将 `branch1`的某个`commit1`合并到`branch2`当中
切换到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) - [聊下git pull --rebase](https://www.cnblogs.com/wangiqngpei557/p/6056624.html)

View File

@ -50,12 +50,14 @@ PS如果浏览器不支持则这句话只解析为一条简单的语句,
## 严格模式和普通模式的区别 ## 严格模式和普通模式的区别
### 1、全局变量显式声明 > 下面列举几条严格模式的内容。
### 全局变量显式声明
在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。 在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。
### 2、禁止this关键字指向全局对象 ### 禁止this关键字指向全局对象
```javascript ```javascript
var foo = function () { var foo = function () {
@ -66,16 +68,15 @@ PS如果浏览器不支持则这句话只解析为一条简单的语句,
``` ```
上方代码中普通模式打印的是window。严格模式下打印的是undefined。 上方代码中普通模式打印的是window。严格模式下打印的是undefined。
### 3、创设eval作用域 ### 创设eval作用域
### 2、禁止使用with语句 ### 禁止使用with语句
因为with语句无法在编译时就确定属性到底归属哪个对象。 因为with语句无法在编译时就确定属性到底归属哪个对象。
### 构造函数必须通过new实例化对象 ### 构造函数必须通过new实例化对象
构造函数必须通过new实例化对象否则报错。因为this为undefined此时无法设置属性。 构造函数必须通过new实例化对象否则报错。因为this为undefined此时无法设置属性。
@ -94,12 +95,12 @@ PS如果浏览器不支持则这句话只解析为一条简单的语句,
上方代码中,如果在严格模式下,则会报错。 上方代码中,如果在严格模式下,则会报错。
### 5、为了让代码更安全,禁止函数内部遍历调用栈 ### 为了让代码更安全,禁止函数内部遍历调用栈
### 6、严格模式下无法删除变量 ### 严格模式下无法删除变量
### 7~10 属性相关 ### 属性相关
普通模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败。严格模式下,将报错。 普通模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败。严格模式下,将报错。

View File

@ -527,7 +527,7 @@ console.log(fn1(1, 2)); //输出结果3
如果我把第一个参数改一下,改成: 如果我把第一个参数改一下,改成:
20180312_2017.png ![](http://img.smyhvae.com/20180312_2017.png)
此时打印结果是:`vae smyh`。 此时打印结果是:`vae smyh`。

View File

@ -209,12 +209,9 @@ Symbol是函数但并不是构造函数。创建一个Symbol数据类型
console.log(mySymbol); //打印结果Symbol() console.log(mySymbol); //打印结果Symbol()
``` ```
打印结果: 打印结果:
20180317_1134.png ![](http://img.smyhvae.com/20180317_1134.png)
下面来讲一下Symbol的使用。 下面来讲一下Symbol的使用。
@ -234,10 +231,9 @@ Symbol是函数但并不是构造函数。创建一个Symbol数据类型
console.log(obj); console.log(obj);
``` ```
上面的代码中我们尝试给obj添加一个Symbol类型的属性值但是添加的时候不能采用`.`这个符号,而是应该用`属性选择器`的方式。打印结果: 上面的代码中我们尝试给obj添加一个Symbol类型的属性值但是添加的时候不能采用`.`这个符号,而是应该用`属性选择器`的方式。打印结果:
20180317_1145.png ![](http://img.smyhvae.com/20180317_1134.png)
现在我们用for in尝试对上面的obj进行遍历 现在我们用for in尝试对上面的obj进行遍历
@ -261,11 +257,10 @@ Symbol是函数但并不是构造函数。创建一个Symbol数据类型
打印结果: 打印结果:
20180317_1817.png ![](http://img.smyhvae.com/20180317_1134.png)
从打印结果中可以看到for in、for of 遍历时不会遍历Symbol属性。 从打印结果中可以看到for in、for of 遍历时不会遍历Symbol属性。
### 创建Symbol属性值时传参作为标识 ### 创建Symbol属性值时传参作为标识
如果我通过 Symbol()函数创建了两个值,这两个值是不一样的: 如果我通过 Symbol()函数创建了两个值,这两个值是不一样的:
@ -279,7 +274,7 @@ Symbol是函数但并不是构造函数。创建一个Symbol数据类型
console.log(mySymbol2); //打印结果Symbol() console.log(mySymbol2); //打印结果Symbol()
``` ```
20180317_1733.png ![](http://img.smyhvae.com/20180317_1134.png)
上面代码中,倒数第三行的打印结果也就表明了,二者的值确实是不相等的。 上面代码中,倒数第三行的打印结果也就表明了,二者的值确实是不相等的。
@ -288,7 +283,6 @@ Symbol是函数但并不是构造函数。创建一个Symbol数据类型
既然Symbol()是函数,函数就可以传入参数,我们可以通过参数的不同来作为**标识**。比如: 既然Symbol()是函数,函数就可以传入参数,我们可以通过参数的不同来作为**标识**。比如:
```javascript ```javascript
//在括号里加入参数来标识不同的Symbol //在括号里加入参数来标识不同的Symbol
let mySymbol1 = Symbol('one'); let mySymbol1 = Symbol('one');
@ -302,21 +296,18 @@ Symbol是函数但并不是构造函数。创建一个Symbol数据类型
打印结果: 打印结果:
20180317_1739.png ![](http://img.smyhvae.com/20180317_1134.png)
### 定义常量 ### 定义常量
Symbol 可以用来定义常量: Symbol 可以用来定义常量:
```javascript ```javascript
const MY_NAME = Symbol('my_name'); const MY_NAME = Symbol('my_name');
``` ```
### 内置的 Symbol 值 ### 内置的 Symbol 值
除了定义自己使用的 Symbol 值以外ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。 除了定义自己使用的 Symbol 值以外ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。
@ -326,7 +317,6 @@ Symbol 可以用来定义常量:
对象的`Symbol.iterator`属性,指向该对象的默认遍历器方法。 对象的`Symbol.iterator`属性,指向该对象的默认遍历器方法。
## async函数异步函数 ## async函数异步函数
### 概述 ### 概述

View File

@ -35,7 +35,7 @@ ES6中的字符串扩展用得少而且逻辑相对简单。如下
打印结果: 打印结果:
20180402_1050.png ![](http://img.smyhvae.com/20180402_1050.png)
## 数值的扩展 ## 数值的扩展
@ -115,11 +115,11 @@ ES6中的字符串扩展用得少而且逻辑相对简单。如下
上面的布局中有三个button标签我们通过`getElementsByTagName`获取到的`btnArray`实际上是**伪数组**,并不是真实的数组: 上面的布局中有三个button标签我们通过`getElementsByTagName`获取到的`btnArray`实际上是**伪数组**,并不是真实的数组:
20180402_1116.png ![](http://img.smyhvae.com/20180402_1116.png)
既然`btnArray`是伪数组,它就不能使用数组的一般方法,否则会报错: 既然`btnArray`是伪数组,它就不能使用数组的一般方法,否则会报错:
20180402_1121.png ![](http://img.smyhvae.com/20180402_1121.png)
解决办法:采用`Array.from`方法将`btnArray`这个伪数组转换为真数组即可: 解决办法:采用`Array.from`方法将`btnArray`这个伪数组转换为真数组即可:
@ -129,7 +129,7 @@ ES6中的字符串扩展用得少而且逻辑相对简单。如下
然后就可以使用数组的一般方法了: 然后就可以使用数组的一般方法了:
20180402_1125.png ![](http://img.smyhvae.com/20180402_1125.png)
### 扩展2 ### 扩展2
@ -259,7 +259,7 @@ ES6中的字符串扩展用得少而且逻辑相对简单。如下
打印结果: 打印结果:
20180404_2240.png ![](http://img.smyhvae.com/20180404_2240.png)
上图显示成功将obj1和obj2的属性复制给了obj3。 上图显示成功将obj1和obj2的属性复制给了obj3。
@ -280,7 +280,7 @@ ES6中的字符串扩展用得少而且逻辑相对简单。如下
打印结果: 打印结果:
20180404_2251.png ![](http://img.smyhvae.com/20180404_2251.png)
上方代码中obj2本身是没有属性的但是通过`__proto__`属性和obj1产生关联于是就可以获得obj1里的属性。 上方代码中obj2本身是没有属性的但是通过`__proto__`属性和obj1产生关联于是就可以获得obj1里的属性。
@ -307,13 +307,6 @@ ES6中的字符串扩展用得少而且逻辑相对简单。如下

View File

@ -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实例销毁之前调用。在这一步实例仍然完全可用。
+ destroyedVue 实例销毁后调用。调用后Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
## Vue 2.0的生命周期函数
![](http://img.smyhvae.com/20180422_1650.png) ![](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实例销毁之前调用。在这一步实例仍然完全可用。
- destroyedVue 实例销毁后调用。调用后Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
举例1创建期间的生命周期函数
```html ```html
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@ -59,20 +68,29 @@
data: { data: {
msg: 'hello vuejs' msg: 'hello vuejs'
}, },
// 这是第1个生命周期函数表示实例完全被创建出来之前会执行它
beforeCreate: function () { beforeCreate: function () {
console.log('1.0 beforeCreate', this.msg); console.log('01 beforeCreate', this.msg);
} //注意:在 beforeCreate 生命周期函数执行的时候data 和 methods 中的 数据都还没有没初始化
, },
// 这是第2个生命周期函数
created: function () { created: function () {
console.log('2.0 created', this.msg); console.log('02 created', this.msg);
} //注意:如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作
, },
// 这是第3个生命周期函数表示 模板已经在内存中编辑完成了,但是尚未把模板渲染到页面中
beforeMount: function () { beforeMount: function () {
console.log('3.0 beforeMount', this.msg); console.log('03 beforeMount', this.msg);
} // 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串
, },
// 这是第4个生命周期函数表示内存中的模板已经真实的挂载到了页面中用户已经可以看到渲染好的页面了
mounted: function () { 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