vue
第一篇:邂逅vue
为什么学习Vuejs?
简单的认识一下Vue.js
Vue.js安装
开发环境?https://vuejs.org/js/vue.js
生产环境?https://vuejs.org/js/vue.min.js
- 方式三:NPM安装
- 后续通过webpack和CLI的使用,我们使用该方式。
Vue的初体验
-
我们来做我们的第一个Vue程序,体验一下Vue的响应式 -
代码做了什么事情? -
我们来阅读JavaScript代码,会发现创建了一个Vue对象。 -
创建Vue对象的时候,传入了一些options:{}
- {}中包含了el属性:该属性决定了这个Vue对象挂载到哪一个元素上,很明显,我们这里是挂载到了id为app的元素上
- {}中包含了data属性:该属性中通常会存储一些数据
- 这些数据可以是我们直接定义出来的,比如像上面这样。
- 也可能是来自网络,从服务器加载的。
-
浏览器执行代码的流程:
- 执行到10~13行代码显然出对应的HTML
- 执行第16行代码创建Vue实例,并且对原HTML进行解析和修改。
-
并且,目前我们的代码是可以做到响应式的。
<div id="app">
<p v-if="seen">现在可以看到我了</p>
<a :href="url">点击我</a>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
seen: false,
url: "https://learning.dcloud.io/#/?vid=6"
}
});
</script>
Vue中的MVVM
-
什么是MVVM呢?
- 通常我们学习一个概念,最好的方式是去看维基百科(对,千万别看成了百度百科)
- https://zh.wikipedia.org/wiki/MVVM
- 维基百科的官方解释,我们这里不再赘述。
-
我们直接来看Vue的MVVM
创建Vue实例传入的options
Vue的生命周期
第二篇:基础语法
插值操作
1.Mustache
-
如何将data中的文本数据,插入到HTML中呢?
- 我们已经学习过了,可以通过Mustache语法(也就是双大括号)。
- Mustache: 胡子/胡须.
-
我们可以像下面这样来使用,并且数据是响应式的
2.v-once
代码如下:
<div id="app">
<h2>{{message}}</h2>
<h2 v-once>{{message}}</h2>//只展现一次message的数据,当后面的message发生改变的时候,这个message不会发生改变。
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
}
})
</script>
3.v-html
<div id="app">
<h2>{{url}}</h2> //输出:<a href="https://www.bilibili.com/video/BV15741177Eh?p=14&spm_id_from=pageDriver">b站一下<a>
<h2 v-html="url"></h2> //输出:b站一下
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
url: '<a href="https://www.bilibili.com/video/BV15741177Eh?p=14&spm_id_from=pageDriver">b站一下<a> '
}
})
</script>
4.v-text
<div id="app">
<h2>{{message}}</h2> //你好啊!!!
<h2 v-text="message"></h2> //你好啊!!!
<!-- message会覆盖掉h2里面的内容 -->
<!-- 、//如果只有文本的话可以用<v-text></v-text> -->
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
}
})
</script>
5.v-pre
6.v-clock
绑定属性:
1.v-bind介绍和使用
v-bind基础
<div id="app">
<img v-bind:src="imgURL" alt="">
<img :src="imgURL" alt="">
<!-- 两者效果一样 -->
<!--v-bind的语法糖写法 v-bind---》: -->
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
imgURL: "../../images/back-2.jpg"
}
})
</script>
v-bind绑定class
-
很多时候,我们希望动态的来切换class,比如:
- 当数据为某个状态时,字体显示红色。
- 当数据另一个状态时,字体显示黑色。
-
绑定class有两种方式:
绑定方式:对象语法
用法一:直接通过{}绑定一个类
<h2 :class="{'active': isActive}">Hello World</h2>
用法二:也可以通过判断,传入多个值
<h2 :class="{'active': isActive, 'line': isLine}">Hello World</h2>
用法三:和普通的类同时存在,并不冲突
注:如果isActive和isLine都为true,那么会有title/active/line三个类
<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>
用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello World</h2>
案例:
<div id="app">
<!-- 固定的class和动态的的class可以共存,不会相互覆盖 -->
<h2 class="title" :class="{active: isActive,line:isLine}">{{message}}</h2>
<h2 class="title" :class="getClass()">{{message}}</h2>
<!-- 调用函数的时候要加小括号,下面的按钮中的那个可以省略 -->
<button @click="btnClick">切换颜色</button>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
isActive: true,
isLine: true
},
methods: {
btnClick: function() {
this.isActive = !this.isActive
},
getClass: function() {
return {
active: this.isActive,
line: this.isLine
// 要用到本作用域中的变量的时候记住加this.
}
}
}
})
</script>
绑定方式:数组语法
数组语法有下面这些用法:
用法一:直接通过{}绑定一个类
<h2 :class="['active']">Hello World</h2>
用法二:也可以传入多个值
<h2 :class=“[‘active’, 'line']">Hello World</h2>
用法三:和普通的类同时存在,并不冲突
注:会有title/active/line三个类
<h2 class="title" :class=“[‘active’, 'line']">Hello World</h2>
用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello World</h2>
v-bind绑定style
绑定方式一:对象语法
:style="{color: currentColor, fontSize: fontSize + 'px'}"
style后面跟的是一个对象类型
对象的key是CSS属性名称
对象的value是具体赋的值,值可以来自于data中的属性
案例:
<div id="app">
<!-- 50px必须加上一个单引号,否则当成以后个变量解析的 -->
<h2 :style="{fontSize: '50px'}">{{message}}</h2>
<!-- finalsize直接当成一个变量使用了 -->
<h2 :style="{fontSize: finalsize}">{{message}}</h2>
<h2 :style="{fontSize: finalsize1+'px',color:finalcolor}">{{message}}</h2>
<h2 :style="getStyle()">{{message}}</h2>
<!-- 是方法,记住一定要加() -->
<p :style="{'fontSize': finalsize,color:finalcolor}">{{fullName}}</p>
<!-- 使用computed不需要加() -->
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
finalsize: '100px',
finalsize1: 100,
finalcolor: 'red',
firstName: "Lebron",
lastName: "James"
},
// 计算属性
computed: {
fullName() {
return this.firstName + " " + this.lastName
}
},
//方法
methods: {
getStyle() {
return {
fontSize: this.finalsize1 + 'px',
color: this.finalcolor
}
}
}
})
</script>
绑定方式二:数组语法
<div v-bind:style="[baseStyles, overridingStyles]"></div>
style后面跟的是一个数组类型
多个值以,分割即可
计算属性
1.什么是计算属性
-
我们知道,在模板中可以直接通过插值语法显示一些data中的数据。 -
但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示
- 比如我们有firstName和lastName两个变量,我们需要显示完整的名称。
- 但是如果多个地方都需要显示完整的名称,我们就需要写多个{{firstName}} {{lastName}}
-
我们可以将上面的代码换成计算属性: -
OK,我们发现计算属性是写在实例的computed选项中的。 -
计算属性中也可以进行一些更加复杂的操作,比如下面的例子
<div id="app">
<h2>总价格:{{totalPrice}}</h2>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
books: [{
id: 110,
name: '代码大全',
prise: 119
}, {
id: 111,
name: '代码大全',
prise: 112
}, {
id: 112,
name: '代码大全',
prise: 101
}, {
id: 113,
name: '代码大全',
prise: 109
}]
},
computed: {
totalPrice: function() {
let result = 0;
for (let i = 0; i < this.books.length; i++) {
result += this.books[i].prise;
}
return result;
}
}
})
</script>
2.计算属性的setter和getter
- 每个计算属性都包含一个getter和一个setter
- 在上面的例子中,我们只是使用getter来读取。
- 在某些情况下,你也可以提供一个setter方法(不常用)。
- 在需要写setter的时候,代码如下:
3.计算属性的缓存
- 我们可能会考虑这样的一个问题:
- methods和computed看起来都可以实现我们的功能,
- 那么为什么还要多一个计算属性这个东西呢?
- 原因:计算属性会进行缓存,如果多次使用时,计算属性只会调用一次。
事件监听
- 在前端开发中,我们需要经常和用于交互。
- 这个时候,我们就必须监听用户发生的时间,比如点击、拖拽、键盘事件等等
- 在Vue中如何监听事件呢?使用v-on指令
- v-on****介绍
- 作用:绑定事件监听器
- 缩写:@
- 预期:Function | Inline Statement | Object
- 参数:event
1.v-on基础
- 这里,我们用一个监听按钮的点击事件,来简单看看v-on的使用
- 下面的代码中,我们使用了v-on:click="counter++”
- 另外,我们可以将事件指向一个在methods中定义的函数
- 注:v-on也有对应的语法糖:
<h2>{{counter}}</h2>
<button v-on:click='increment(10)'>+1</button>
<button @click='decrement'>-1</button>
//定义各种各样的方法
methods: {
increment(count) {
console.log(count);
this.counter++;
},
decrement() {
this.counter--;
}
}
2.v-on参数
-
当通过methods中定义方法,以供@click调用时,需要注意参数问题: -
情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。
- 但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去
-
情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。
3.v-on修饰符
<!--停止冒泡-- >
<button @click.stop= "doThis">< /button>
<!--阻止默认行为-->
<button @click.prevent="doThis">< /button>
<!--阻止默认行为,没有表达式-->
<form @submit.prevent></ form>
< !--串联修饰符-->
<button @click.stop.prevent="doThis"></button>
<!--键修饰符,键别名-->
<input @keyup.enter="onEnter">
<!--键修饰符,键代码-->
<input @keyup.13="onEnter">
<!--点击回调只会触发-次-- >
<button @click.once="doThis"></button>
条件判断
1.v-if、v-else-if、v-else
<div id="app">
<span v-if="username">
<label for="one">用户账号:</label>
<input type="text" id="one" placeholder="填写用户账号" key="one">
</span>
<span v-else>
<label for="two">用户邮箱:</label>
<input type="text" id="two" placeholder="填写用户邮箱" key="two">
</span>
<button @click="username=!username">切换类型</button>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
username: true
}
})
</script>
案例小问题:
-
小问题:
- 如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。
- 但是按道理讲,我们应该切换到另外一个input元素中了。
- 在另一个input元素中,我们并没有输入内容。
- 为什么会出现这个问题呢?
-
问题解答:
- 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。
- 在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了。
-
解决方案:
- 如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key
- 并且我们需要保证key的不同
2.v-show
<div id="app">
<h2 v-if="isShow" id="one">{{message}}</h2>
<h2 v-show="isShow" id="two">{{message}}</h2>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
isShow: true
}
})
</script>
循环遍历
1.v-for遍历数组
<div id="app">
<ul>
<li v-for="(item,index) of name">{{index+1}}.{{item}}</li>
</ul>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
name: ['fhkjsd', 'adfga', 'sdfasd', 'asdfgsd']
}
})
</script>
2.v-for遍历对象
- v-for可以用户遍历对象:
- 比如某个对象中存储着你的个人信息,我们希望以列表的形式显示出来。
遍历对象
<div id="app">
<!-- 1.在遍历对象的过程中,如果只是获取一个值,那么获取到的是 value -->
<ul>
<li v-for="item of foo">{{item}}</li>
</ul>
<!-- 2.获取key和value 格式:(value,key) -->
<ul>
<li v-for="(item,key) of foo">{{key}}:{{item}}</li>
</ul>
<!-- 3.获取key,value和索引 格式:(value,key,index) -->
<ul>
<li v-for="(item,key,index) of foo">{{index}}-{{key}}:{{item}}</li>
</ul>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
foo: {
name: 'why', //name:是key,why:是value。
age: '21',
height: '1.78'
}
}
})
</script>
3.组件的key属性
-
官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性。 -
为什么需要这个key属性呢(了解)?
-
当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点
- 我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的。
- 即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?
-
所以我们需要使用key来给每个节点做一个唯一标识
- Diff算法就可以正确的识别此节点
- 找到正确的位置区插入新的节点。
-
所以一句话,key的作用主要是为了高效的更新虚拟DOM。
4.检测数组更新(splice:重点)
- n因为Vue是响应式的,所以当数据发生变化时,Vue会自动检测数据变化,视图会发生对应的更新。
- Vue中包含了一组观察数组编译的方法,使用它们改变数组也会触发视图的更新。
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
响应式的:
<div id="app">
<ul>
<li v-for="item of letters">{{item}}</li>
</ul>
<button @click="btnClick">点击</button>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
letters: ['a', 'b', 'c', 'd']
},
methods: {
btnClick() {
//1.push的方法;在最后面添加元素。
// this.letters.push('aaa')
//括号中可以跟多个,一次遍历
//2.pop(); 删除数数组中最后一个元素;
// this.letters.pop();
//3.shift(); 删除数组中的第一个元素;
// this.letters.shift();
//4.unshift(); 在数组的最前面添加元素;
// this.letters.unshift('aaaa');
//括号中可以跟多个,一次遍历
//5.splice();
//splice()的作用;删除元素,插入元素,替换元素
//splice(start); 从第几个元素开始 第一参数都一样
// this.letters.splice(start);
//如果是删除元素,第二个参数传入的是你要删除几个元素(如果没有传值就删除后面所有的元素)
// this.letters.splice(start,(要删除元素的个数));
//替换元素:第二个参数,传入0,并且后面跟上要插入的元素。都好分隔;
// this.letters.splice(start,(要替换元素的个数),(要替换的元素,替换几个写几个));this.letters.splice(1,3,'b','d','d')
//插入元素:
// this.letters.splice(1, 0, 'x', 'y', 'z')
//6.sort():排序
// this.letters.sort()
//7.reverse():反转元素;
this.letters.reverse()
//注意:通过索引直接修改数组中的元素 这不是响应式的
// this.letters[0] = 'aaaaa'
}
}
})
</script>
v-model
1.表单绑定v-model
-
表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。 -
Vue中使用v-model指令来实现表单元素和数据的双向绑定。 -
案例的解析:
- 当我们在输入框输入内容时
- 因为input中的v-model绑定了message,所以会实时将输入的内容传递给message,message发生改变。
- 当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生响应的改变。
- 所以,通过v-model实现了双向的绑定。
-
当然,我们也可以将v-model用于textarea元素
<div id="app">
<!-- 双向绑定 -->
<input type="text" v-model=" message ">
<!-- 单向绑定 获得data中的message的值 -->
<input type="text" :value=" message ">
<!-- 单向绑定 input:获取输入框中的内容事件,输入的值后改变message-->
<input type="text" v-on:input="valueChange">
<input type="text" :value=" message " @input="message=$event.target.value">
<h2>{{message}}</h2>
</div>
<script text="javascript ">
let app = new Vue({
el: "#app ",
data: {
message: "你好啊!!! ",
},
methods: {
valueChange(event) {
this.message = event.target.value;
}
}
})
</script>
2.v-model原理
<input type="text" v-model="message">
等同于
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
3.v-model:radio和v-model:checkbox
-
当存在多个单选框时 -
复选框分为两种情况:单个勾选框和多个勾选框 -
单个勾选框:
- v-model即为布尔值。
- 此时input的value并不影响v-model的值。
-
多个复选框:
- 当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。
- 当选中某一个时,就会将input的value添加到数组中。
案例:
<div id="app">
<label for="agree">
<input type="checkbox" id="agree" v-model="isAgree">喜欢cyl
</label>
<h2>你的选择是:{{isAgree}}</h2>
<button :disabled="!isAgree">下一步</button>
<br>
<br> <br>
<input type="checkbox" value="篮球" v-model="hoddy">篮球
<input type="checkbox" value="足球" v-model="hoddy">足球
<input type="checkbox" value="乒乓球" v-model="hoddy">乒乓球
<input type="checkbox" value="羽毛球" v-model="hoddy">羽毛球
<h2>你的爱好是:{{hoddy}}</h2>
<br>
<br>
<br>
<label v-for="item of origilhoddy" :for="item">
<input type="checkbox" :value="item" :id="item" v-model="hoddy">{{item}}
</label>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
isAgree: true, //单选框对应的是布尔值
hoddy: [], //多选框对应的是数组
origilhoddy: ['篮球', '足球', '乒乓球', '橄榄球', '羽毛球']
}
})
</script>
4.v-model:select
<div id="app">
<!-- 选择一个值 -->
<select v-model="mySelect">
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="orange">橘子</option>
</select>
<p>你喜欢的水果:{{mySelect}}</p>
<br>
<select v-model="mySelects" multiple>
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="orange">橘子</option>
</select>
<p>你喜欢的水果:{{mySelects}}</p>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
mySelect: 'apple',
mySelects: []
}
})
</script>
5.值绑定
-
初看Vue官方值绑定的时候,我很疑惑:what the hell is that? -
但是仔细阅读之后,发现很简单,就是动态的给value赋值而已:
- 我们前面的value中的值,可以回头去看一下,都是在定义input的时候直接给定的。
- 但是真实开发中,这些input的值可能是从网络获取或定义在data中的。
- 所以我们可以通过v-bind:value动态的给value绑定值。
- 这不就是v-bind吗?
-
这不就是v-bind在input中的应用吗?搞的我看了很久,搞不清他想将什么。 -
这里不再给出对应的代码,因为会用v-bind,就会值绑定的应用了。
6.修饰符
-
lazy修饰符:
- 默认情况下,v-model默认是在input事件中同步输入框的数据的。
- 也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。
- lazy修饰符可以让数据在失去焦点或者回车时才会更新:
-
number修饰符:
- 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类 型进行处理。
- 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。
- number修饰符可以让在输入框中输入的内容自动转成数字类型:
-
trim修饰符:
- 如果输入的内容首尾有很多空格,通常我们希望将其去除
- trim修饰符可以过滤内容左右两边的空格
<div id="app">
<input type="text" v-model.lazy="message">
<p>当前内容:{{message}}</p>
年龄:<input type="number" v-model.number="age">
<p>年龄:{{age}} 类型{{typeof age}}</p>
<input type="text" v-model.trim="message">
<p>当前内容:----{{message}}------</p>
</div>
第三篇:组件化开发(重点)
认识组件化
1.什么是组件化
-
人面对复杂问题的处理方式:
- 任何一个人处理信息的逻辑能力都是有限的
- 所以,当面对一个非常复杂的问题时,我们不太可能一次性搞定一大堆的内容。
- 但是,我们人有一种天生的能力,就是将问题进行拆解。
- 如果将一个复杂的问题,拆分成很多个可以处理的小问题,再将其放在整体当中,你会发现大的问题也会迎刃而解。
-
组件化也是类似的思想:
- 如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。
- 但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。
-
我们将一个完整的页面分成很多个组件。 -
每个组件都用于实现页面的一个功能块。 -
而每一个组件又可以进行细分。
2.Vue组件化思想
- 组件化是Vue.js中的重要思想
- 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
- 任何的应用都会被抽象成一颗组件树。
注册组件
注册组件的基本步骤
-
组件的使用分成三个步骤:
-
我们来看看通过代码如何注册组件 -
查看运行结果:
- 和直接使用一个div看起来并没有什么区别。
- 但是我们可以设想,如果很多地方都要显示这样的信息,我们是不是就可以直接使用来完成呢?
注册组件步骤解析
组件的其他补充(了解)
1.全局组件和局部组件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jpDFBYUF-1638328245757)(https://gitee.com/hzg-sss/typora-picture/raw/master/img/image-20210917103355282.png)]
2.父组件和子组件
3.注册组件语法糖
-
在上面注册组件的方式,可能会有些繁琐。
- Vue为了简化这个过程,提供了注册的语法糖。
- 主要是省去了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替。
-
语法糖注册全局组件和局部组件:
4.模板的分离写法
组件的数据存放
1.组件可以访问Vue实例数据吗?
2.组件数据的存放
- 组件自己的数据存放在哪里呢?
- 组件对象也有一个data属性(也可以有methods等属性,下面我们有用到)
- 只是这个data属性必须是一个函数
- 而且这个函数返回一个对象,对象内部保存着数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-imbA9jQz-1638328245767)(https://gitee.com/hzg-sss/typora-picture/raw/master/img/image-20210917113741987.png)]
- 为什么data在组件中必须是一个函数呢?
- 首先,如果不是一个函数,Vue直接就会报错。
- 其次,原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。
父子组件的通信
1.引言
2.父级向子级传递
2.1props基本用法
2.2props数据验证
3.子集向父级传递
3.父子组件的访问方式:
3.1$children
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UxfDNeJW-1638328245776)(https://gitee.com/hzg-sss/typora-picture/raw/master/img/image-20210917145920562.png)]
3.2**:** $refs
-
$children的缺陷:
- 通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。
- 但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。
- 有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs
-
$refs的使用:
- $refs和ref指令通常是一起使用的。
- 首先,我们通过ref给某一个子组件绑定一个特定的ID。
- 其次,通过this.$refs.ID就可以访问到该组件了。
3.3:$parent
3.4非父子组件通信
-
刚才我们讨论的都是父子组件间的通信,那如果是非父子关系呢?
- 非父子组件关系包括多个层级的组件,也包括兄弟组件的关系。
-
在Vue1.x的时候,可以通过
d
i
s
p
a
t
c
h
和
dispatch和
dispatch和broadcast完成
- $dispatch用于向上级派发事件
- $broadcast用于向下级广播事件
- 但是在Vue2.x都被取消了
-
在Vue2.x中,有一种方案是通过中央事件总线,也就是一个中介来完成。
- 但是这种方案和直接使用Vuex的状态管理方案还是逊色很多。
- 并且Vuex提供了更多好用的功能,所以这里我们暂且不讨论这种方案,后续我们专门学习Vuex的状态管理。
插槽
1.编译作用域
-
在真正学习插槽之前,我们需要先理解一个概念:编译作用域。 -
官方对于编译的作用域解析比较简单,我们自己来通过一个例子来理解这个概念: -
我们来考虑下面的代码是否最终是可以渲染出来的:
- 中,我们使用了isShow属性。
- isShow属性包含在组件中,也包含在Vue实例中。
-
答案:最终可以渲染出来,也就是使用的是Vue实例的属性。 -
为什么呢?
- 官方给出了一条准则:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。
- 而我们在使用的时候,整个组件的使用过程是相当于在父组件中出现的。
- 那么他的作用域就是父组件,使用的属性也是属于父组件的属性。
- 因此,isShow使用的是Vue实例中的属性,而不是子组件的属性。
2.为什么使用插槽
3.**如何封装这类组件呢?**slot
4.slot基本使用
5.具名插槽slot
<div id="app">
<cpn><button slot="middle">按钮</button></cpn>
<cpn><span slot="left">哈哈哈哈</span></cpn>
</div>
<template id="cpn">
<div>
<slot name="left"><span>左边</span></slot>
<slot name="middle"><span>中间的</span></slot>
<slot name="right"><span>右边</span></slot>
<slot><button>按钮替换</button></slot>
</div>
</template>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
},
components: {
cpn: {
template: '#cpn'
}
}
})
</script>
6.作用域插槽
<div id="app">
<cpn></cpn>
<cpn>
<template slot-scope="slotone">
<div>
<span v-for="item of slotone.data">{{item}}- </span>
</div>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<!-- data:这是自己起的名字 -->
<slot :data="pLanguages">
<ul>
<li v-for="item of pLanguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
},
components: {
cpn: {
template: '#cpn',
data() {
return {
pLanguages: ['大熊', '熊大', '熊二', '光头强']
}
}
}
}
})
</script>
第四篇:Vue Cli相关
1.什么是Vue Cli
-
如果你只是简单写几个Vue的Demo程序, 那么你不需要Vue CLI. -
如果你在开发大型项目, 那么你需要, 并且必然需要使用Vue CLI
- 使用Vue.js开发大型应用时,我们需要考虑代码目录结构、项目结构和部署、热加载、代码单元测试等事情。
- 如果每个项目都要手动完成这些工作,那无以效率比较低效,所以通常我们会使用一些脚手架工具来帮助完成这些事情。
-
CLI是什么意思?
- CLI是Command-Line Interface, 翻译为命令行界面, 但是俗称脚手架.
- Vue CLI是一个官方发布 vue.js 项目脚手架
- 使用 vue-cli 可以快速搭建Vue开发环境以及对应的webpack配置.
2.Vue Cli使用的前提 - Node
-
安装NodeJS
- 可以直接在官方网站中下载安装.
- 网址: http://nodejs.cn/download/
-
检测安装的版本
- 默认情况下自动安装Node和NPM
- Node环境要求8.9以上或者更高版本
-
什么是NPM呢**?**
- NPM的全称是Node Package Manager
- 是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。
- 后续我们会经常使用NPM来安装一些开发过程中依赖包.
注:cnpm安装
-
由于国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像。 -
你可以使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:npm install -g cnpm --registry=https://registry.npm.taobao.org 这样就可以使用 cnpm 命令来安装模块了:cnpm install [name]
注:具体的安装可以分为命令行安装和图像化界面安装,看哪个适合,这一部分初学者最好是自己先摸索如何安装和使用,如果自己没有配置或者安装好,找已经走过本阶段的学长学姐或则朋友指导如何安装。
流程:
- 安装node.js
- 更改node.js在电脑中的位置
- 配置环境
- (cnpm安装)
- 安装脚手架
- 安装一系列的依赖(npm install xxxx)
- 写作品
第五篇:vue-router详解
认识路由
什么是路由?
-
说起路由你想起了什么?
- 路由是一个网络工程里面的术语。
- 路由(routing)就是通过互联的网络把信息从源地址传输到目的地址的活动. — 维基百科
-
额, 啥玩意? 没听懂
- 在生活中, 我们有没有听说过路由的概念呢? 当然了, 路由器嘛.
- 路由器是做什么的? 你有想过吗?
- 路由器提供了两种机制: 路由和转送.
- 路由是决定数据包从来源到目的地的路径.
- 转送将输入端的数据转移到合适的输出端.
-
路由中有一个非常重要的概念叫路由表.
- 路由表本质上就是一个映射表, 决定了数据包的指向.
后端路由阶段
前端路由阶段
-
前后端分离阶段:
- 随着Ajax的出现, 有了前后端分离的开发模式.
- 后端只提供API来返回数据, 前端通过Ajax获取数据, 并且可以通过JavaScript将数据渲染到页面中.
- 这样做最大的优点就是前后端责任的清晰, 后端专注于数据上, 前端专注于交互和可视化上.
- 并且当移动端(iOS/Android)出现后, 后端不需要进行任何处理, 依然使用之前的一套API即可.
- 目前很多的网站依然采用这种模式开发.
-
单页面富应用阶段:
- 其实SPA最主要的特点就是在前后端分离的基础上加了一层前端路由.
- 也就是前端来维护一套路由规则.
-
前端路由的核心是什么呢?
- 改变URL,但是页面不进行整体的刷新。
- 如何实现呢?
前端路由的规则
1.URL的hash
- URL的hash
- URL的hash也就是锚点(#), 本质上是改变window.location的href属性.
- 我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新
2.HTML5的history模式:pushState
3.HTML5的history模式:replaceState
4.HTML5的history模式:go
- 补充说明:
- 上面只演示了三个方法
- 因为 history.back() 等价于 history.go(-1)
- history.forward() 则等价于 history.go(1)
- 这三个接口等同于浏览器界面的前进后退
vue-router基础
1.认识vue-router
-
目前前端流行的三大框架, 都有自己的路由实现:
- Angular的ngRouter
- React的ReactRouter
- Vue的vue-router
-
当然, 我们的重点是vue-router
- vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。
- 我们可以访问其官方网站对其进行学习: https://router.vuejs.org/zh/
-
vue-router是基于路由和组件的
- 路由用于设定访问路径, 将路径和组件映射起来.
- 在vue-router的单页面应用中, 页面的路径的改变就是组件的切换.
2.安装和使用vue-router
-
后续开发中我们主要是通过工程化的方式进行开发的.
-
使用vue-router的步骤:
- 第一步: 创建路由组件
- 第二步: 配置路由映射: 组件和路径映射关系
- 第三步: 使用路由: 通过和
2.1创建router实例
2.2挂在到Vue实例中
2.3创建路由组件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8mSbM93D-1638328245789)(https://gitee.com/hzg-sss/typora-picture/raw/master/img/image-20210917215258160.png)]
2.4配置组件和路径的映射关系
2.5使用路由
-
: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个标签.(跳转路由) -
: 该标签会根据当前的路径, 动态渲染出不同的组件. -
网页的其他内容, 比如顶部的标题/导航, 或者底部的一些版权信息等会和处于同一个等级. -
在路由切换时, 切换的是挂载的组件, 其他内容不会发生改变.
2.6最终的效果如下:
3.路由的补充说明:
3.1路由的默认路径
- 配置解析:
- 我们在routes中又配置了一个映射.
- path配置的是根路径: /
- redirect是重定向, 也就是我们将根路径重定向到/home的路径下, 这样就可以得到我们想要的结果了.
3.2HTML的History模式
效果如下图:
3.3router-link补充
3.4修改linkActiveClass
3.5路由代码跳转
3.6动态路由
- 在某些情况下,一个页面的path路径可能是不确定的,比如我们进入用户界面时,希望是如下的路径:
- /user/aaaa或/user/bbbb
- 除了有前面的/user之外,后面还跟上了用户的ID
- 这种path和Component的匹配关系,我们称之为动态路由(也是路由传递数据的一种方式)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F7ZDJpfR-1638328245807)(https://gitee.com/hzg-sss/typora-picture/raw/master/img/image-20210917222234793.png)]
4.路由懒加载
4.1认识路由的懒加载
-
官方给出了解释:
- 当打包构建应用时,Javascript 包会变得非常大,影响页面加载。
- 如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了
-
官方在说什么呢?
- 首先, 我们知道路由中通常会定义很多不同的页面.
- 这个页面最后被打包在哪里呢? 一般情况下, 是放在一个js文件中.
- 但是, 页面这么多放在一个js文件中, 必然会造成这个页面非常的大.
- 如果我们一次性从服务器请求下来这个页面, 可能需要花费一定的时间, 甚至用户的电脑上还出现了短暂空白的情况.
- 如何避免这种情况呢? 使用路由懒加载就可以了.
-
路由懒加载做了什么?
- 路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块.
- 只有在这个路由被访问到的时候, 才加载对应的组件
4.2路由懒加载的效果
4.3懒加载的方式
- 方式一: 结合Vue的异步组件和Webpack的代码分析.
const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};=
const About = resolve => require(['../components/About.vue'], resolve);
- 方式三: 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.
const Home = () => import('../components/Home.vue')
5.嵌套路由
5.1认识嵌套路由
-
嵌套路由是一个很常见的功能
- 比如在home页面中, 我们希望通过/home/news和/home/message访问一些内容.
- 一个路径映射一个组件, 访问这两个路径也会分别渲染两个组件.
-
路径和组件的关系如下:
- 实现嵌套路由有两个步骤:
- 创建对应的子组件, 并且在路由映射中配置对应的子路由.
- 在组件内部使用标签.
5.2嵌套路由的实现
1.定义两个组件
2.router中路由嵌套
3.实际页面中跳转路由
4.效果图;
5.3嵌套默认路径
6.传递参数
6.1准备工作
- 为了演示传递参数, 我们这里再创建一个组件, 并且将其配置好
-
第一步: 创建新的组件Profile.vue -
第二步: 配置路由映射 -
第三步: 添加跳转的
6.2传递参数的方式
6.2.1传递参数方式一:
6.2.2传递参数方式二: JavaScript代码
6.3获取路由参数
-
获取参数通过$route对象获取的.
- 在使用了 vue-router 的应用中,路由对象会被注入每个组件中,赋值为 this.$route ,并且当路由切换时,路由对象会被更新。
-
通过$route获取传递的信息如下:
6.4
r
o
u
t
e
和
route和
route和router是什么区别的
-
r
o
u
t
e
和
route和
route和router是有区别的
-
r
o
u
t
e
r
为
V
u
e
R
o
u
t
e
r
实
例
,
想
要
导
航
到
不
同
U
R
L
,
则
使
用
router为VueRouter实例,想要导航到不同URL,则使用
router为VueRouter实例,想要导航到不同URL,则使用router.push方法
- $route为当前router跳转对象里面可以获取name、path、query、params等
7.导航守卫
7.1为什么使用导航守卫
7.2导航守卫使用
7.3导航守卫的补充
-
补充一:如果是后置钩子, 也就是afterEach, 不需要主动调用next()函数. -
补充二: 上面我们使用的导航守卫, 被称之为全局守卫.
-
更多内容, 可以查看官网进行学习:
8.keep-alive遇见vue-router(重点)
第六篇:Vuex详解
1.认识Vuex
1.1Vuex是做什么的?
1.2管理什么状态呢?
1.3单界面的状态管理
1.4单页面状态管理的实现
-
在这个案例中,我们有木有状态需要管理呢?没错,就是个数counter。 -
counter需要某种方式被记录下来,也就是我们的State。 -
counter目前的值需要被显示在界面中,也就是我们的View部分。 -
界面发生某些操作时(我们这里是用户的点击,也可以是用户的input),需要去更新状态,也就是我们的Actions -
这不就是上面1.3的流程图了吗?
1.5多页面状态管理
1.6Vuex状态管理图例
- 一起在来看一幅官方给出的图片
2.Vuex的基本使用
2.1通过案例来了解Vuex的使用
-
我们还是简单的实现一个计数器的案例 -
首先,我们需要在某个地方存放我们的Vuex代码:
- 这里,我们先创建一个文件夹store,并且在其中创建一个index.js文件
- 在index.js文件中写入如下代码:
2.2挂载到Vue实例中
- 其次,我们让所有的Vue组件都可以使用这个store对象
- 来到main.js文件,导入store对象,并且放在new Vue中
- 这样,在其他Vue组件中,我们就可以通过this.$store的方式,获取到这个store对象了
2.3使用Vuex的count
-
好的,这就是使用Vuex最简单的方式了。 -
我们来对使用步骤,做一个简单的小节:
- 1.提取出一个公共的store对象,用于保存在多个组件中共享的状态
- 2.将store对象放置在new Vue对象中,这样可以保证在所有的组件中都可以使用到
- 3.在其他组件中使用store对象中保存的状态即可
- 通过this.$store.state.属性的方式来访问状态
- 通过this.$store.commit(‘mutation中方法’)来修改状态
- mutation中的方法是对state中定义的变量或则其他东西进行修改。(重点)
-
注意事项:
- 我们通过提交mutation的方式,而非直接改变store.state.count。
- 这是因为Vuex可以更明确的追踪状态的变化,所以不要直接改变store.state.count的值。
3.Vuex核心概念
-
Vuex有几个比较核心的概念:
- State
- Getters
- Mutation
- Action
- Module
-
我们对它进行一一介绍.
3.1 State
3.1.1 State单一状态树
3.1.2 Getters
3.1.3 Getters作为参数和传递参数
- 如果我们已经有了一个获取所有年龄大于20岁学生列表的getters, 那么代码可以这样来写
- getters默认是不能传递参数的, 如果希望传递参数, 那么只能让getters本身返回另一个函数.
3.2 Mutation
3.2.1Mutation状态更新
mutations:{
increment(state){
state.count++
}
}
increment: function(){
this.$store.commit('increment')
}
3.2.2Mutation传递参数(Payload)
- 但是如果参数不是一个呢?
- 比如我们有很多参数需要传递.
- 这个时候, 我们通常会以对象的形式传递, 也就是payload是一个对象.
- 这个时候可以再从对象中取出相关的信息.
3.2.3Mutation提交风格
this.$store.commit({
type:'changeCount',
count:100
})
- Mutation中的处理方式是将整个commit的对象作为payload使用, 所以代码没有改变, 依然如下:
changeCount(State,payload){
state.count = payload.count
}
3.2.4Mutation响应规则
3.2.5Mutation常量类型– 概念
-
我们来考虑下面的问题:
- 在mutation中, 我们定义了很多事件类型(也就是其中的方法名称).
- 当我们的项目增大时, Vuex管理的状态越来越多, 需要更新状态的情况越来越多, 那么意味着Mutation中的方法越来越多.
- 方法过多, 使用者需要花费大量的经历去记住这些方法, 甚至是多个文件间来回切换, 查看方法名称, 甚至如果不是复制的时候, 可能还会出现写错的情况.
-
如何避免上述的问题呢?
- 在各种Flux实现中, 一种很常见的方案就是使用常量替代Mutation事件的类型.
- 我们可以将这些常量放在一个单独的文件中, 方便管理以及让整个app所有的事件类型一目了然.
-
具体怎么做呢?
- 我们可以创建一个文件: mutation-types.js, 并且在其中定义我们的常量.
- 定义常量时, 我们可以使用ES2015中的风格, 使用一个常量来作为函数的名称.
3.2.6Mutation同步函数
-
通常情况下, Vuex要求我们Mutation中的方法必须是同步方法.
- 主要的原因是当我们使用devtools时, 可以devtools可以帮助我们捕捉mutation的快照.
- 但是如果是异步操作, 那么devtools将不能很好的追踪这个操作什么时候会被完成.
-
比如我们之前的代码, 当执行更新时, devtools中会有如下信息: 图1 -
但是, 如果Vuex中的代码, 我们使用了异步函数: 图2
-
你会发现state中的info数据一直没有被改变, 因为他无法追踪到. -
So, 通常情况下,不要再mutation中进行异步的操作
3.3Action
3.3.1Action的基本定义
3.3.2Action的分发
3.3.3Action返回的Promise
3.4认识Model(可以看看实例)
3.4.1认识Module
3.4.2Module局部状态
3.4.3Actions的
3.5项目结构
- 当我们的Vuex帮助我们管理过多的内容时, 好的项目结构可以让我们的代码更加清晰.
第七篇:网络模块 axios
1.如何选择网络模块
-
Vue中发送网络请求有非常多的方式, 那么, 在开发中, 如何选择呢?
- 选择一: 传统的Ajax是基于XMLHttpRequest(XHR)
-
为什么不用它呢?
- 非常好解释, 配置和调用方式等非常混乱.
- 编码起来看起来就非常蛋疼.
- 所以真实开发中很少直接使用, 而是使用jQuery-Ajax
-
选择二: 在前面的学习中, 我们经常会使用jQuery-Ajax
-
为什么不选择它呢?
- 首先, 我们先明确一点: 在Vue的整个开发中都是不需要使用jQuery了.
- 那么, 就意味着为了方便我们进行一个网络请求, 特意引用一个jQuery, 你觉得合理吗?
- jQuery的代码1w+行.
- Vue的代码才1w+行.
- 完全没有必要为了用网络请求就引用这个重量级的框架.
-
选择三: 官方在Vue1.x的时候, 推出了Vue-resource.
- Vue-resource的体积相对于jQuery小很多.
- 另外Vue-resource是官方推出的.
-
为什么不选择它呢?
- 在Vue2.0退出后, Vue作者就在GitHub的Issues中说明了去掉vue-resource, 并且以后也不会再更新.
- 那么意味着以后vue-reource不再支持新的版本时, 也不会再继续更新和维护.
- 对以后的项目开发和维护都存在很大的隐患.
-
选择四: 在说明不再继续更新和维护vue-resource的同时, 作者还推荐了一个框架: axios为什么不用它呢?
- axios有非常多的优点, 并且用起来也非常方便.
- 稍后, 我们对他详细学习.
2.axios
2.1为什么选择axios?
-
n为什么选择axios? 作者推荐和功能特点、 -
n功能特点
- 在浏览器中发送 XMLHttpRequests 请求
- 在 node.js 中发送 http请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
2.2axios请求方式
- 支持多种请求方式:
- axios(config)
- axios.request(config)
- axios.get(url[, config])
- axios.delete(url[, config])
- axios.head(url[, config])
- axios.post(url[, data[, config]])
- axios.put(url[, data[, config]])
- axios.patch(url[, data[, config]])
2.2.1发送get请求演示
2.2.2发送并发请求
- 有时候, 我们可能需求同时发送两个请求
- 使用axios.all, 可以放入多个请求的数组.
- axios.all([]) 返回的结果是一个数组,使用 axios.spread 可将数组 [res1,res2] 展开为 res1, res2
2.2.3全局配置
- 在上面的示例中, 我们的BaseURL是固定的
- 事实上, 在开发中可能很多参数都是固定的.
- 这个时候我们可以进行一些抽取, 也可以利用axiox的全局配置
2.2.4常见的配置选项
3.axios实例
- 为什么要创建axios的实例呢?
- 当我们从axios模块中导入对象时, 使用的实例是默认的实例.
- 当给该实例设置一些默认配置时, 这些配置就被固定下来了.
- 但是后续开发中, 某些配置可能会不太一样.
- 比如某些请求需要使用特定的baseURL或者timeout或者content-Type等.
- 这个时候, 我们就可以创建新的实例, 并且传入属于该实例的配置信息.
axios封装
4.拦截器
1.如何使用拦截器?
2.拦截器中都做了什么?
4.3.拦截器中都做了什么?
- 响应的失败拦截中,可以根据status判断报错的错误码,跳转到不同的错误提示页面。
知识点补充
1.高阶函数
1.1filter,map,reduce
1.1.1filter函数的使用:
- filter中的回调函数有一个要求:必须返回一个boolean值
- true:当返回true时,函数的内部会自动将这次回调的n加入到新的数组中
- false:当返回false时,函数的内部会过滤掉这次的n
<script text="javascript">
const nums = [10, 20, 30, 40, 50, 91, 73, 50]
let newNums = nums.filter(function(n) {
return n < 100
})
console.log(newNums);
</script>
1.1.2map函数的使用:
- 让数组中的值都有一次变化的话用map(例如:数组中的每一个值都乘以2)
let new2Nums = newNums.map(function(n) {
return n * 2
})
console.log(new2Nums);
1.1.3.reduce的使用:
//preValue:前面值得累加,有点像sum
//n:数组中的值,
let total = new2Nums.reduce(function(preValue, n) {
return preValue + n;
}, 0)
console.log(total);
2.箭头函数:
1.定义函数的方式:function
const aaa = function(){
}
2.对象字面量中定义函数
const obj = {
bbb:function(){
},
bbb(){
}
}
3.ES6中的箭头函数
const ccc = (参数列表)=>{
}
<script text="javascript">
//参数问题:
//1.1放入两个参数
const sum = (num1,num2)=>{
return num1+num2
}
//1.2放入一个参数(一个参数的时候,参数括号可以省略)
const power =num=>{
return num * num
}
//2函数代码块有多行代码的时候
const sss = test=>{
//1.打印HelloWord
console.log(HelloWord)
//2.打印total
console.log(total)
}
//2.1函数代码块有一行代码块的时候 不用写return
const nul = (num1,num2)=>num1+num2
</script>
3.this的指向问题
在非箭头函数下, this 指向调用其所在函数的对象,而且是离谁近就是指向谁(此对于常规对象,原型链, getter & setter等都适用);构造函数下,this与被创建的新对象绑定;DOM事件,this指向触发事件的元素;内联事件分两种情况,bind绑定, call & apply 方法等, 容以下一步一步讨论。箭头函数也会穿插其中进行讨论。
3.1全局环境下:
在全局环境下,this 始终指向全局对象(window), 无论是否严格模式;
console.log(this.document === document); // true
// 在浏览器中,全局对象为 window 对象:
console.log(this === window); // true
this.a = 37;
console.log(window.a); // 37
3.2函数直接调用
普通函数内部的this分两种情况,严格模式和非严格模式。
非严格模式下,this 默认指向全局对象window
function f1(){
return this;
}
f1() === window; // true
而严格模式下, this为undefined
function f2(){
"use strict"; // 这里是严格模式
return this;
}
f2() === undefined; // true
3.3对象中的this
对象内部方法的this指向调用这些方法的对象,
- 函数的定义位置不影响其this指向,this指向只和调用函数的对象有关。
- 多层嵌套的对象,内部方法的this指向离被调用函数最近的对象(window也是对象,其内部对象调用方法的this指向内部对象, 而非window)。
<script text="javascript">
//1
var o = {
prop: 37,
f: function() {
return this.prop;
}
};
console.log(o.f()); //37
var a = o.f;
console.log(a()): //undefined
var o = {prop: 37};
function independent() {
return this.prop;
}
o.f = independent;
console.log(o.f()); // logs 37
//2
o.b = {
g: independent,
prop: 42
};
console.log(o.b.g()); // logs 42
</script>
3.1箭头函数中的this
箭头函数中的this引用的是最近作用域中的this
待总结… console.log(newNums);
##### 1.1.2map函数的使用:
- 让数组中的值都有一次变化的话用**map**(例如:数组中的每一个值都乘以2)
```vue
let new2Nums = newNums.map(function(n) {
return n * 2
})
console.log(new2Nums);
1.1.3.reduce的使用:
//preValue:前面值得累加,有点像sum
//n:数组中的值,
let total = new2Nums.reduce(function(preValue, n) {
return preValue + n;
}, 0)
console.log(total);
2.箭头函数:
1.定义函数的方式:function
const aaa = function(){
}
2.对象字面量中定义函数
const obj = {
bbb:function(){
},
bbb(){
}
}
3.ES6中的箭头函数
const ccc = (参数列表)=>{
}
<script text="javascript">
//参数问题:
//1.1放入两个参数
const sum = (num1,num2)=>{
return num1+num2
}
//1.2放入一个参数(一个参数的时候,参数括号可以省略)
const power =num=>{
return num * num
}
//2函数代码块有多行代码的时候
const sss = test=>{
//1.打印HelloWord
console.log(HelloWord)
//2.打印total
console.log(total)
}
//2.1函数代码块有一行代码块的时候 不用写return
const nul = (num1,num2)=>num1+num2
</script>
3.this的指向问题
在非箭头函数下, this 指向调用其所在函数的对象,而且是离谁近就是指向谁(此对于常规对象,原型链, getter & setter等都适用);构造函数下,this与被创建的新对象绑定;DOM事件,this指向触发事件的元素;内联事件分两种情况,bind绑定, call & apply 方法等, 容以下一步一步讨论。箭头函数也会穿插其中进行讨论。
3.1全局环境下:
在全局环境下,this 始终指向全局对象(window), 无论是否严格模式;
console.log(this.document === document); // true
// 在浏览器中,全局对象为 window 对象:
console.log(this === window); // true
this.a = 37;
console.log(window.a); // 37
3.2函数直接调用
普通函数内部的this分两种情况,严格模式和非严格模式。
非严格模式下,this 默认指向全局对象window
function f1(){
return this;
}
f1() === window; // true
而严格模式下, this为undefined
function f2(){
"use strict"; // 这里是严格模式
return this;
}
f2() === undefined; // true
3.3对象中的this
对象内部方法的this指向调用这些方法的对象,
- 函数的定义位置不影响其this指向,this指向只和调用函数的对象有关。
- 多层嵌套的对象,内部方法的this指向离被调用函数最近的对象(window也是对象,其内部对象调用方法的this指向内部对象, 而非window)。
<script text="javascript">
//1
var o = {
prop: 37,
f: function() {
return this.prop;
}
};
console.log(o.f()); //37
var a = o.f;
console.log(a()): //undefined
var o = {prop: 37};
function independent() {
return this.prop;
}
o.f = independent;
console.log(o.f()); // logs 37
//2
o.b = {
g: independent,
prop: 42
};
console.log(o.b.g()); // logs 42
</script>
3.1箭头函数中的this
箭头函数中的this引用的是最近作用域中的this
待总结…
|