day01
1. Vue简介
一套用于构建用户界面的 <font color=red>
渐进式框架</font>
2. 初识Vue
2.1 搭建Vue开发环境
-
第一步:去
<a href="https://v2.cn.vuejs.org/">
Vue2官网</a>
,下载依赖包。 -
第二步:在
html
文件中引入vue.js
。<!-- 引入Vue --> <script type="text/javascript" src="../../js/vue.js"></script>
输出一下
Vue
构造函数:console.log(Vue)
,看是否配置成功。 -
第三步:编写脚本关闭生产提示。
//阻止 vue 在启动时生成生产提示 Vue.config.productionTip = false
注意:如果上述方法无法关闭,可直接操作
vue.js
修改productionTip
的值为false
。 -
第四步:安装开发者工具,打开浏览器的【插件管理】,直接拖动
.crx
文件到浏览器即可。 -
第五步:配置页签图标,直接复制
favicon.ico
到根目录即可。
2.2 一个Hello效果
- 实现效果:
-
核心代码:
<!-- 准备好一个容器 --> <div id="demo"> <h1>Hello,{{school}}</h1> </div> <script type="text/javascript" > // 创建Vue实例,并传入配置对象 new Vue({ el:'#demo', //用于指定当前Vue实例服务于哪个容器,值为CSS选择器字符串 data:{ // data用于配置数据,数据可以直接在模板中使用,值暂时写成一个对象 school:'尚硅谷' } }) </script>
-
总结:
- 想让
Vue
工作,就要创建一个<font color="red">
Vue实例</font>
,且要传入一个配置对象。 demo
容器中的代码被称为<font color="red">
模板</font>
,它依然符合HTML
规范,只是混入了一些特殊的Vue
语法。<font color="red">
el 配置</font>
:用于指定当前Vue
实例服务于哪个容器,值为:css
选择器字符串。<font color="red">
data 配置</font>
:用于配置数据,数据可以直接在模板中使用,值暂时写成一个对象(以后还会写成函数)。
- 想让
2.3 分析Hello效果
-
Vue
实例和容器是<font color="red">
一一对应</font>
的,真实开发中一般只有一个Vue
实例,而且还会配合组件一起使用。 -
data
中的数据只要发生改变,模板中用到该数据的地方就会自动更新。 -
{{xxx}}
中的xxx
要写js
表达式,且xxx
可以自动读取到data
中的属性。 -
复习一个点:【
js
表达式】与【js
语句】-
表达式:会产生一个值,可以放在任何一个需要值的地方,例如:
(1).
1
(2).a
(3).x > = 18 ? '成年' : '未成年'
(4).200 - 2
(5).arr.map()
等等…
-
语句(代码): 不会产生值,只是控制代码走向,例如:
(1).
if ( ) {}
(2).for ( ) {}
(3).try {} catch (err) {}
等等…
-
-
相关代码:
<!-- 准备好一个容器 -->
<div id="demo">
<h1>Hello,{{school}}</h1>
<h1>Hello,{{address}}</h1>
<h1>Hello,{{school.toUpperCase()}}</h1>
<h1>Hello,{{school.toUpperCase().slice(0,2)}}</h1>
<h1>Hello,{{floor}}</h1>
<h1>Hello,{{floor > 6 ? '高楼层' : '低楼层'}}</h1>
<h1>Hello,{{1+1}}</h1>
<h1>Hello,1+1</h1>
<h1>Hello,{{floor+1}}</h1>
</div>
<!-- 创建Vue实例 -->
<script type="text/javascript" >
new Vue({
el:'#demo',
data:{
school:'atguigu',
address:'宏福科技园',
floor:19
}
})
</script>
3. 了解开发者工具
- 视角一
2. 视角二
4. Vue的模板语法
4.1 插值与指令
-
插值语法(简单):
功能:用于操作标签体,可以在标签体的指定位置插入数据。
写法:{{xxx}}
,xxx
是js
表达式,且可以自动读取到data
中配置的所有属性。 -
指令语法(复杂):
功能:用于操作标签(标签属性、标签体、绑定事件…)
举例:v-bind:href = "xxx"
,xxx 是js
表达式,且可以自动读取到data
中配置的所有属性。 -
备注:
Vue
中有很多的指令,形式都是v-???
,此处我们只是拿v-bind
举个例子。 -
务必搞懂如下代码:
<a
v-bind:href="url"
a="url"
v-bind:b="url"
c="1+1"
v-bind:d="1+1"
e="url.toUpperCase()"
v-bind:f="url.toUpperCase()"
>
点我去{{school}}学习
</a>
<script>
new Vue({
el:'#demo',
data:{
school:'尚硅谷',
url:'http://www.atguigu.com'
}
})
</script>
4.2 v-bind
的简写
v-bind:
可以简写为:
- 只有
v-bind
指令才能简写为:
别的指令不行。 - 其他的指令有其他的简写形式、但并不是所有的指令都有简写形式。
5. 数据绑定
-
Vue
中有两种绑定数据的方式:- 单向数据绑定(
v-bind
):数据只能从data
流向页面。 - 双向数据绑定(
v-model
):数据不仅能从data
流向页面,也能从页面流回data
。
- 单向数据绑定(
-
注意点:
v-model
目前只能用在输入类(表单类)元素上(以后还能用写在组件标签上)。v-model
默认收集的是value
值,所以v-model:value="xxx"
可以简写为v-model="xxx"
。
-
核心代码:
<!-- 准备好一个容器--> <div id="demo"> <h1>欢迎来到{{school}}</h1> <!-- 单向绑定:<input type="text" v-bind:value="address"> <br> --> <!-- 双向绑定:<input type="text" v-model:value="address"> --> <br> <!-- 上面的13、14行的简写形式如下 --> 单向绑定:<input type="text" :value="address"> <br> 双向绑定:<input type="text" v-model="address"> <!-- 下面这行代码是有问题的,会报错,因为v-model只能用在输入类(表单类)元素上 --> <!-- <a v-model:href="url">点我去{{school}}学习2</a> --> </div> <script type="text/javascript" > new Vue({ el:'#demo', data:{ school:'尚硅谷', url:'http://www.atguigu.com', address:'宏福科技园' } }) </script>
6. el 与 data 的写法
6.1 el 的三种写法
-
第一种写法:值为
css
选择器字符串new Vue({ el:'#demo' //****** })
-
第二种写法:值为一个真实
DOM
元素 —— 几乎不用,了解即可。new Vue({ el:document.getElementById('demo'), //****** })
-
第三种写法:使用
$mount
方法去替代el
配置。new Vue(/******/).$mount('#demo')
6.2 data 的两种写法
-
第一种(对象式)
data:{ school:'尚硅谷' }
-
第二种(函数式)—— 最近不用,以后会用。
data(){ return { school:'尚硅谷' } }
7. 理解MVVM
M
:模型(Model
) :data
中的数据。V
:视图(View
) :模板。VM
:视图模型(ViewModel
) : Vue实例对象。
8. 认识一下vm
-
vm
身上有很多$
开头的属性或方法,这是给我们程序员用的(但也不是都用)。 -
data
中所配置的属性,也不知道怎么了(后面会详细说),最终都出现在了vm
身上。 -
vm
身上所有的属性,以及顺着vm
能找到的东西,都能在模板中直接使用,但往往我们使用的只是那些:配置项中所写的东西。 -
务必搞懂如下代码:
<!-- 准备好一个容器--> <div id="demo"> <h1>{{school}}欢迎你!</h1> <h2>测试1:{{a}}</h2> <h2>测试2:{{b}}</h2> <h2>测试3:{{_c}}</h2> <h2>测试4:{{$attrs}}</h2> <h2>测试5:{{toString}}</h2> <h2>测试6:{{d}}</h2> </div> <script type="text/javascript"> Object.prototype.d = 9 let vm = new Vue({ el: '#demo', data: { school: '尚硅谷', a: 1, b: 2 } }) // 输出Vue实例对象 —— vm console.log(vm) </script>
day02
1. 复习Object.defineProperty
-
Object.defineProperty
,能给对象追加属性,并且可以对属性进行“高级定制”。//定义一个对象 let person = {name:'张三',sex:'女'} //通过Object.defineProperty,也可以给person对象追加一个age属性,且可以对age进行“高级定制”。 Object.defineProperty(person,'age',{ value:90,//值 enumerable:true, //控制属性是否可以枚举(是否参与遍历),默认值false configurable:true, //控制属性是否可以删除,默认值false writable:true,//控制属性是否可以被修改,默认值false })
-
Object.defineProperty
的get
与set
配置://定义一个number变量 let number = 18 // 定义一个person对象 let person = {name:'张三',sex:'女'} //借助Object.defineProperty去追加age属性 Object.defineProperty(person,'age',{ enumerable:true, //get函数(getter)何时执行?—— 有人读取person对象的age属性时执行 //get函数(getter)中的this是谁? —— 当前对象(person) get:function peiqi(){ console.log('getter执行了',this) return number }, //set函数(setter)何时会被调用? —— 有人修改person对象的age属性时执行 //get函数(setter)中的this是谁? —— 当前对象(person) set:function qiaozhi(value){ console.log('有人修改了person的age属性,值为:',value,this) number = value } })
2. 数据代理
2.1 何为数据代理
通过一个对象代理对另一个对象中属性的操作(读/写)。
2.2 Vue中的数据代理
-
前情提要:我们
new Vue(options)
时传入的那个data
,Vue
收到后放在了vm
上,名为_data
。 -
Vue
中的数据代理:通过vm
来对_data
中属性的操作(读/写)。 -
Vue
中数据代理的好处:模板中可以更加方便的操作_data
中的数据,例如:若无数据代理,这么写:
{{_data.name}}
—— 很麻烦。若有数据代理,这么写:
{{name}}
—— 香!注意:此时我们先不关注
_data
中为什么也有getter
、setter
,过几天就会说。
2.3 数据代理的原理
-
遍历
_data
对象中所有的属性,通过Object.defineProperty()
一个一个都添加到vm
上。 -
随后
vm
上就拥有了_data
中所有的属性,且都有自己的getter
、setter
。 -
getter
、setter
内部操作(读/写)的是_data
中对应的属性。
3. 事件处理
3.1 事件绑定
-
使用
v-on:xxx
或@xxx
绑定事件,xxx
是事件名,同原生DOM
事件名。<button v-on:click="showTel">点我查看学校电话1</button> <button @click="showTel">点我查看学校电话2</button>
-
事件的回调函数,要配置在
methods
中(data
中写数据、methods
中写方法)。 -
Vue
在触发事件回调时,会传入一个默认的参数 ——事件对象(event
) 。 -
methdos
中的函数最终也会出现在vm
上(<font color="red">
但不存在数据代理</font>
)。const vm = new Vue({ el:'#demo', data:{ school:'尚硅谷', tel:'10086', }, methods:{ showTel:(event)=>{ console.log(this) alert(this.tel) } } }) console.log(vm)
通常情况下,由
Vue
管理的函数(目前只学了:data
函数、methods
中的函数),请务必写成普通函数,这样才能保证:this
是vm
,一旦写成了箭头函数,this
就不再是vm
了。
3.2 事件传参
- 不传递参数:
@click="test1"
,test1
方法会收到一个event
(事件对象)。 - 传一个参数:
@click="test2(6)"
,test2
方法只会收到一个6
。 - 传多个参数:
@click="test3(6,7,8)"
,test3
方法会收到:6、7、8
。 - 传参+事件对象:
@click="test4(6,$event)"
,test4
方法会收到:事件对象
、6
。 - 传递的参数也可以是
data
中的数据,例如@click="test5(school)"
。
以下写法有点傻:
<button @click="test($event)">按钮</button>
<button @click="test()">按钮</button>
3.3 事件修饰符
-
prevent
:可以阻止默认行为。 -
stop
:可以阻止冒泡。 -
once
:事件只触发一次。 -
事件修饰符可以串联:
<div @click="test" class="wraper"> <a href="xxx" @click.prevent.stop="test">按钮</a> </div>
3.4 键盘事件
-
Vue
中的按键别名:- 回车 =>
enter
- 删除 =>
delete
(退格 、 删除 按键) - 退出 =>
esc
- 空格 =>
space
- 换行 =>
tab
(必须配合keydown
去使用) - 上 =>
up
- 下 =>
down
- 左 =>
left
- 右 =>
right
- 回车 =>
-
也可以使用
event.c去指定具体的按键,例如:
@keyup.13` 绑定回车。 -
有四个系统修饰键,用法比较特殊(了解即可),分别是:
ctrl
、alt
、shift
、meta
,规则如下:- 若配合
keydown
使用:正常触发事件。 - 若配合
keyup
使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
- 若配合
4. 姓名案例
4.1 插值语法实现
-
总结:用插值语法实现姓名案例,不是很好,因为模板过于复杂。
-
核心代码:
<span>{{firstName.slice(0,1).toUpperCase() + firstName.slice(1)}}-{{lastName}}</span>
4.2 methods实现
-
总结:使用
methods
去实现姓名案例,比使用插值好了一些,但存在一些问题:- 没有缓存,多次使用同样的值,函数会执行多次,效率不高。
- 无关数据若发生变化,也会导致方法执行。
-
核心代码:
methods:{ getFullName(){ console.log('getFullName') return this.firstName.slice(0,1).toUpperCase() + this.firstName.slice(1) + '-' + this.lastName }, }
5. 计算属性
学习计算属性前,请先把【姓名案例】分别用:插值语法、methods,去实现一下。
- 定义:要用的数据(属性)不存在,要根据已有数据(属性)计算得来。
- 原理:底层是通过
Objcet.defineProperty
实现的。 - 优势:与
methods
实现姓名案例相比,内部有缓存机制,效率更高,且调试方便。
5.1 get
函数
get
函数何时调用?
- 初次读取
fullName
时。- 计算
fullName
所【依赖的数据】发生改变时。get
函数中的this
谁? ——vm
。注意:计算属性最终也会出现在
vm
上,在模板中可直接使用,<font color="red">
但千不要加.get()
!</font>
5.2 set
函数(用的少)
set
函数何时调用?—— 仅当计算属性被修改时。
set
函数中的this
是谁? ——vm
。什么是修改计算属性?
这是修改:
this.fullName = 'li-si'
这是读取:
this.fullName
注意:
this.firstName = 'li'
,这是修改firstName
代码示例:
computed:{
fullName:{
get(){
/**********/
}
set(value){
/**********/
}
}
}
5.3 简写方式
-
什么时候才能简写?—— 计算属性不会修改时(不需要
set
函数时),才能用简写形式。 -
语法实例:
computed:{ fullName(){ return xxxxx } }
6. 天气案例
如果回调函数的逻辑很简短,那么可以写在引号里:
<button @click="isHot = !isHot">切换天气</button>
day03
1. 监视属性
1.1 基本使用
监视属性又称侦听器,学习监视属性前,请先完成:天气案例。
-
作用:当被监视的属性变化时, 回调函数(
handler
)自动调用,至于回调函数中做什么,要看具体需求。 -
具体编码:
watch:{ isHot:{ handler(newValue,oldValue){ /*********/ } } }
-
注意点:
- 被监视的可以是:属性(
data
),也可以是计算属性(computed
)。 - 监视的属性必须存在,才能进行监视,若监视了不存在的属性,也不会报错!
- 被监视的可以是:属性(
1.2 立即监视
- 作用:让
Vue
初次渲染时,数据还没有发生变化,就调用一下监视的回调函数(handler
) - 具体配置:
immediate:true
1.3 深度监视
Vue
底层一直可以监测对象内部值的改变(且无论对象有“深”)。Vue
给我们提供的watch
配置,默认不监测对象内部属性的改变。- 配置
deep:true
可以监测对象内部属性的改变。 - 使用
watch
时,要根据数据的具体结构,来决定是否采用深度监视。
1.4 特殊写法
当数据层级较深,但只想监视里面的某一个数据时候,可以不开启深度监视,只针对某个属性进行监视,例如:
new Vue({
el:'#demo',
data:{
a:{
b:{
c:{
d:1
}
}
}
},
watch:{
'a.b.c.d':{
handler(value){
console.log('a.b.c.d变化了')
}
}
}
})
1.5 简写形式
-
明确:当不需要【立即监视】、【深度监视】的时候,才可以用简写形式。
-
示例代码(
isHot
函数,就相当于完整写法中的handler
):watch:{ isHot(){ /*********/ } }
1.6 $watch(了解即可)
通过 vm.$watch
也可以进行监视
vm.$watch('isHot',{
handler(newValue,oldValue){
/******/
}
})
2.梳理配置项
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>梳理配置项</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="demo">
<!-- a怎么用 -->
<!-- <h1 :x="a">{{a}}</h1> -->
<!-- <input type="text" v-model="a"> -->
<!-- <button @click="a+=1">点我</button> -->
<!-- b怎么用 -->
<!-- 19行、20行,没有语法上的错误,但使用的没意义 -->
<!-- <h1 :x="b">{{b}}</h1> -->
<!-- <input type="text" v-model="b"> -->
<!-- <button @click="b">点我</button> -->
<!-- <h1>{{b()}}</h1> -->
<!-- c能怎么用 -->
<!-- <h1 :x="c">{{c}}</h1> -->
<!-- 下面这行能写,但要记得,配一个setter -->
<!-- <input type="text" v-model="c"> -->
<h1>{{c}}</h1>
</div>
<script type="text/javascript">
const vm = new Vue({
el:'#demo',
data:{
a:1,
},
methods:{
b(){
console.log('b执行了')
return 99
}
},
computed:{
c(){
return (this.a+1)*10
}
},
watch:{}
})
console.log(vm)
</script>
</body>
</html>
3. computed与watch
computed
和 watch
之间的区别与联系:
-
computed
能完成的功能,watch
都可以完成,且通常computed
的写法会更简便。例如:姓名案例,
computed
、watch
都能完成,但computed
写起来,更简单。 -
watch
能完成的功能,computed
不一定能完成。例如:还做姓名案例,但要求:名改完
1
秒钟后,全名再变。
3.1 computed
- 侧重在【算】,核心是:计算出来的值。
- 靠
return
来输出计算的结果。 - 不能异步计算。
3.2 watch
- 侧重在【监视】,核心是:
xxx
变了,我要做???
事。 - 无需
return
,靠内部逻辑去完成要做的事。 - 能开启异步任务。
4. Vue中使用函数的原则
- 由
Vue
所管理的函数,务必写成普通函数,例如:data
、methods
中的函数、computed
中的函数、watch
中的函数。 - 不是
Vue
所管理的函数,最好写成箭头函数,例如:数组方法的回调函数、ajax
请求的回调函数、定时器的回调函数、Promise
的回调函数等等。
遵循上述两个原则的目的只有一个:让
this
的指向是vm
。
5. 条件渲染
5.1 v-show
- 语法:
v-show="表达式"
。 - 适用于:切换频率较高的场景。
- 特点:不展示的
DOM
元素依然在,仅仅是使用样式隐藏掉了,不破坏DOM
结构。
5.2 v-if
-
语法:
v-if="表达式" v-else-if="表达式" v-else
-
适用于:切换频率较低的场景。
-
特点:不展示的
DOM
元素直接被移除。注意点:
v-if
可以和:v-else-if
、v-else
一起使用,但要求结构不能被“打断”。- 如果使 用
v-if
,可能会出现无法获取元素的问题。
-
实际开发中,以下这个场景我们会使用
v-if
<!-- 准备好一个容器--> <div id="demo"> <h1 v-if="person.age">真实年龄:{{person.age.realAge}}</h1> <button @click="getNetWorkData">获取网络数据</button> </div> <script type="text/javascript"> new Vue({ el:'#demo', data:{ person:{} }, methods: { getNetWorkData(){ this.person = { age:{ foreignAge:29, realAge:45 } } } }, }) </script>
6. 列表渲染
6.1 v-for
指令
- 指令:
v-for
。 - 作用:用于遍历数据,生成多个结构。
- 语法:
v-for="(item,index) in xxx" :key="????"
。
通俗理解:想生成多个谁,就在谁身上加
v-for
,别忘了写key
。
key
的使用原则(同react
):有唯一值就用唯一值(身份证号、手机号、学号…),没有就用索引值。
6.2 详聊 v-for
-
遍历数组
<ul> <li v-for="(item,index) in arr" :key="index"> {{item}} </li> </ul>
-
遍历对象
<li v-for="(value,key,index) in car" :key="index"> {{value}} - {{key}} - {{index}} </li>
-
遍历字符串
<li v-for="(char,index) in str" :key="index"> {{char}} - {{index}} </li>
-
遍历指定次数
<li v-for="(number,index) in 10" :key="index"> {{number}} - {{index}} </li>
-
v-for
很健壮,遍历如下内容都不会报错,并且不会渲染任何内容<h1 v-for="(a,b) in null">尚硅谷</h1> <h1 v-for="(a,b) in undefined">尚硅谷</h1> <h1 v-for="(a,b) in '' ">尚硅谷</h1> <h1 v-for="(a,b) in true ">尚硅谷</h1> <h1 v-for="(a,b) in [] ">尚硅谷</h1>
6.3 人员案例
- 可以使用
watch
、computed
分别去实现一下,发现用computed
更简单。 - 用到了:字符串的
includes
方法,数组的filter
方法。
7. 其它指令
-
我们学过的指令:
v-bind
: 单向数据绑定, 可简写为:xxx
v-model
: 双向数据绑定v-for
: 遍历数组 / 对象 / 字符串 / 指定次数v-on
: 绑定事件监听, 可简写为@
v-if
: 条件渲染(动态控制节点是否存在)v-else-if
: 条件渲染(动态控制节点是否存在)v-else
: 条件渲染(动态控制节点是否存在)v-show
: 条件渲染 (动态控制节点是否展示)
v-text
作用:向其所在的节点中渲染文本内容。
与插值语法的区别:
v-text
会替换掉节点中的内容,{{xx}}
则不会。
v-html
作用:向指定节点中渲染包含
html
结构的文本。
与插值语法的区别:
v-html
会替换掉节点中所有的内容,{{xx}}
则不会。v-html
可以识别html
结构。- 备注:
v-html
存在一些安全性问题,因为结构中很有可能包含恶意脚本。
v-once
v-once
所在节点在初次动态渲染后,就视为静态内容了。- 以后数据的改变不会引起
v-once
所在结构的更新,可以用于优化性能。
v-pre
跳过这个元素和它的子元素的编译过程,一般用在大量不使用
Vue
语法的结构中。
v-cloak
- 本质是一个特殊属性,
Vue
接管容器后,会删掉v-cloak
属性。- 使用
css
配合v-cloak
可以解决网速慢时,页面展示出{{xxx}}
的问题。
8. 数据劫持
8.1 何为数据劫持
-
概念:捕获对象属性变化的一种手段。
前端的响应式框架通常都会对数据进行劫持,这样当数据发生变化时,才能自动更新相关的视图,或执行其他逻辑。
8.2 Vue中的数据劫持
-
具体实现方式:
Vue
会将所有层级的属性,全都改为getter
、setter
的形式,随后放在_data
中。- 当
_data
中的数据放生变化时,对应的setter
会执行,在setter
中:①修改数据、②更新界面。
-
图示:
7.3 总结_数据代理 _数据劫持
-
数据代理(简单,
vm
身上的那点事):- 目的:让程序员更加方便的读取、修改到
_data
中属性。 - 原理:
Object.defineProperty
。 - 体现:
vm
身上有_data
里的所有属性,且有每一个属性,都有自己的proxyGetter
、proxySetter
。
- 当修改
vm
上的属性时,该属性对应的proxySetter
就会调用,去修改_data
中对应的属性。 - 当读取
vm
上的属性时,该属性对应的proxyGetter
就会调用,去读取_data
中对应的属性。
- 目的:让程序员更加方便的读取、修改到
-
数据劫持(
_data
里的那点事):- 目的:为了实现响应式(什么是响应式?—— 数据变页面自动更新),有了数据劫持,就可以捕获到数据的改变,进而重新解析模板,更新界面。
- 原理:
Object.defineProperty
。 - 体现:
_data
身上的每一个属性不直接给值,都变为:reactiveSetter
、reactiveGetter
形式。
- 当修改
_data
上的属性时,该属性对应的reactiveSetter
就会调用。且在reactiveSetter
中Vue会:维护数据、更新页面。 - 当读取
_data
上的属性时,该属性对应的reactiveGetter
就会调用,返回对应的值。