零基础学习 Vue 笔记
HelloWorld
<body>
<div id="root">
<h1>hello, {{name}}</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false; //阻止 vue 在启动时生成生产提示。
//创建 Vue 实例
new Vue({
el: '#root', //el用于指定当前 Vue 实例为哪个容器服务,值通常为 css 选择器字符串
data: { //data 中用于存储数据,数据供 el 所指定的容器去使用,值暂时先写一个对象
name: "校花"
}
})
</script>
</body>
初识 Vue:
- 想让 Vue 工作,就必须创建一个 Vue 实例,且要传入一个配置对象
- root 容器里的代码依然符合 HTML 规范,只不过混入了一些特殊的 Vue 语法
- root 容器里的代码被称之为 Vue 模板
- Vue 实例和容器是一一对应的
- 真实开发中只有一个 Vue 实例,并且会配合着组件一起使用
{{xxx}}
中要写 js 表达式,且 xxx 可以自动读取到data
中的所有属性- js 表达式:一个表达式会产生一个值,可以放在任何一个需要用值的地方,例如:
a
a + b
demo(1)
x === y ? 'a' : 'b'
- js 代码(语句),例如:
if() {}
for() {}
- js 表达式:一个表达式会产生一个值,可以放在任何一个需要用值的地方,例如:
- 一旦
data
中的数据发送改变,那么模板中用到该数据的地方也会自动更新
模板语法
插值语法
功能:用于解析标签体内容(起始标签和结束标签之间的内容),单向绑定
写法:{{xxx}}
,xxx 是 js 表达式,且可以直接读取到 data
中的所有属性
指令语法
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)
写法:Vue中有很多的指令,且形式都是:v-????
以 v-bind
举例:v-bind:href="xxx"
或是简写为 :href="xxx"
,xxx 同样要写 js 表达式,且可以直接读取到data中的所有属性
数据绑定
单向绑定
v-bind
:数据只能从 data
流向页面
<input type="text" v-bind:value="name">
//如下是简写
<input type="text" :value="name">
双向绑定
v-model
:数据不仅能从 data
流向页面,还可以从页面流向 data
- 双向绑定一般都应用在表单类元素上(如:input 、select 等)
v-model:value
可以简写为v-model
,因为v-model
默认收集的就是value
值。
<input type="text" v-model:value="name">
//如下是简写
<input type="text" v-model="name">
el 和 data 的两种写法
el
- new Vue 时候配置 el 属性
- 先创建 Vue 实例,随后再通过
vm.$mount('#root')
指定 el 的值
data
-
对象式
data: { name: "校花" }
-
函数式
data(){ console.log('@@@', this) return { name: "校花" }
- 学习到组件时,
data
必须使用函数式,否则会报错 - Vue 管理的函数,一定不要写箭头函数,一旦写了箭头函数,
this
就不再是 Vue 实例了,而是window
对象
MVVM 模型
- M(模型 Model):对应
data
中的数据 - V(视图 View):页面,也就是模板
- VM(视图模型 ViewModel):Vue 实例对象
data
中所有的属性,最后都会出现在 vm(ViewModel) 身上- vm 身上所有的属性和 Vue 原型上所有属性,在 Vue 模板中都可以直接使用
对应如下代码:
数据代理
defineproperty
defineProperty<T>(o: T, p: PropertyKey, attributes: PropertyDescriptor & ThisType<any>): T;
作用:给对象添加属性
o
:要定义属性的对象p
:对象属性名称attributes
:定义属性的详细信息value
:值enumerable
:控制属性是否可以枚举(能否被遍历到),默认值是false
writable
:控制属性是否可以被修改,默认值是false
configurable
:控制属性是否可以被删除,默认值是false
get()
:当读取到属性时,get
函数(getter)就会被调用,且返回值就是属性的值set(value)
:当修改到属性时,set
函数(setter)就会被调用,且会收到修改的具体值
例如,实现 number
和 age
的双向绑定,即 number
变了 age
变,age
变了 number
变,代码如下:
let number = 18
let person = {
name:"张三",
sex:"男",
}
Object.defineProperty(person, 'age', {
get(){
console.log("读取 age 了")
return number
},
set(value){
console.log("修改 age 了")
number = value
}
})
数据代理
数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
示例代码如下:
<!--通过 obj2 操作 obj1 的属性 x-->
let obj1 = {x:100}
let obj2 = {y:200}
Object.defineProperty(obj2, 'x', {
get(){
return obj1.x;
},
set(value){
obj1.x=value
}
})
Vue 中的数据代理
通过 vm 对象代理 data
对象中属性的操作(读 / 写),基本原理如下:
- 通过
Object.defineProperty()
把data
对象中所有属性添加到 vm 上 - 为每一个添加到 vm 上的属性,都指定一个
getter / setter
- 在
getter/setter
内部去操作(读/写)data
中对应的属性
好处:更加方便的操作 data
中的数据
事件处理
基本使用
- 使用
v-on:xxx
或@xxx
绑定事件,其中 xxx 是事件名 - 事件的回调需要配置在methods对象中,最终会在 vm 上
methods
中配置的函数,不要用箭头函数,否则 this 就不是 vm 了;methods
中配置的函数,都是被 Vue 所管理的函数,this的指向是 vm 或 组件实例对象;@click="demo"
和@click="demo($event)"
效果一致,但后者可以传参;
事件修饰符
prevent
:阻止默认事件(常用)stop
:阻止事件冒泡(常用)once
:事件只触发一次(常用)capture
:使用事件的捕获模式self
:只有event.target
是当前操作的元素时才触发事件passive
:事件的默认行为立即执行,无需等待事件回调执行完毕
键盘事件
Vue 中常用的按键别名:
-
回车 =>
enter
-
删除 =>
delete
(捕获 “删除” 和 “退格” 键) -
退出 =>
esc
-
空格 =>
space
-
换行 =>
tab
(特殊,必须配合keydown
使用) -
上 =>
up
-
下 =>
down
-
左 =>
left
-
右 =>
right
计算和监视属性
computed 计算属性
- 属性:
data
中的叫做属性 - 计算属性:要用的属性不存在,要通过已有属性计算得来。
原理:底层使用了 Objcet.defineproperty
方法提供的 getter
和 setter
get
函数执行时机:
- 初次读取时会执行一次(内部有缓存机制,可以实现复用)
- 当依赖的数据发生改变时会被再次调用
只读不改时可以用简写写法,也就是只有 get()
没有 set()
时:
computed:{
//完整写法
/* 对象名:{
get(){
},
set(value){
}
} */
//简写
函数名(){
}
}
watch 监视属性
属性:data
中的叫做属性
- 当被监视的属性变化时, 回调函数
handler
自动调用, 进行相关操作 - 监视的属性必须存在,才能进行监视
watch
默认不监测对象内部值的改变,配置deep:true
可以监测对象内部值改变(即深度监视)- 监视的两种写法:
- new Vue 时传入
watch
配置 - 通过
vm.$watch
监视
- new Vue 时传入
watch
中的常见配置项:
-
handler
:修改属性时调用 -
deep:true
:深度监视 -
immediate:true
:初始化时让handler
调用一下
当只有 handler
时,可以简写:
watch:{
//正常写法
isHot:{
// immediate:true, //初始化时让handler调用一下
// deep:true,//深度监视
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
},
//简写
isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
}
}
computed
和watch
之间的区别:
computed
能完成的功能,watch
都可以完成watch
能完成的功能,computed
不一定能完成,例如:watch
可以进行异步操作
class 和 style 绑定
class 样式
写法::class="xxx"
, xxx 可以是字符串、对象、数组
- 字符串写法适用于:类名不确定,要动态获取
- 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
- 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
style 样式
:style="{fontSize: xxx}"
,其中 xxx 是动态值
条件渲染
v-if
写法:
v-if="表达式"
v-else-if="表达式"
v-else="表达式"
特点:
- 不展示的 DOM 元素直接被移除
- 适用于切换频率较低的场景
- 注意:
v-if
可以和v-else-if
、v-else
一起使用,但要求结构不能被“打断”
v-show
写法:v-show="表达式"
特点:
- 不展示的 DOM 元素未被移除,仅仅是使用样式隐藏掉
- 适用于切换频率较高的场景
列表渲染
基本列表
v-for
指令:
- 语法:
v-for="(value1, key1) in xxx" :key="yyy"
value1
:data
中对象的属性值key1
:data
中对象的属性名- xxx:
data
中对象的名字
- 作用:用于展示列表数据
- 可遍历:对象、数组、字符串(用的很少)
key
这里就跳过原理,直接给出结论,毕竟是零基础学的 Vue
v-for="(value1, key1) in xxx" :key="yyy"
- 用
key1
作为key
可能会引发的问题:- 若对数据进行逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实 DOM 更新 ==> 界面效果没问题, 但效率低
- 如果结构中还包含输入类的 DOM,会产生错误 DOM 更新 ==> 界面有问题
- 开发中如何选择
key
:- 最好使用每条数据的唯一标识作为
key
, 比如id、手机号、身份证号、学号等唯一值 - 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用
key1
作为key
是没有问题的
- 最好使用每条数据的唯一标识作为
收集表单数据
<input type="text"/>
,则v-model
收集的是value
值,用户输入的就是value
值<input type="radio"/>
(圆形选择),则v-model
收集的是value
值,且要给标签配置value
值<input type="checkbox"/>
(方形选择):- .没有配置
input
的value
属性,那么收集的是 checked(勾选 or 未勾选,是布尔值) - 配置
input
的value
属性:v-model
的初始值是非数组,那么收集的就是 checked(勾选 or 未勾选,是布尔值)v-model
的初始值是数组,那么收集的的就是value
组成的数组
- .没有配置
v-model
的三个修饰符:
lazy
:失去焦点再收集数据number
:输入字符串转为有效的数字trim
:输入首尾空格过滤
常用指令
v-bind
:单向绑定解析表达式, 可简写为:xxx
v-model
:双向数据绑定v-for
:遍历数组 / 对象v-on
:绑定事件监听, 可简写为@
v-if
:条件渲染(动态控制节点是否存存在)v-show
:条件渲染 (动态控制节点是否展示)v-text
:- 作用:向其所在的节点中渲染文本内容
- 与插值语法的区别:
v-text
会替换掉节点中的内容,{{xx}}
则不会
v-html
:- 作用:会替换掉节点中所有的内容,可以识别 html 结构
- 有安全问题,最好别用