目录
- Vue简介
- 模板语法
- 数据绑定
- el与data的两种写法
- Vue中的MVVM
- 数据代理
- 事件处理
Vue简介
- 让Vue工作,就须创建一个Vue实例,且要传入一个配置对象
- demo容器里的代码符合html规范,只不过混入了一些特殊的Vue语法
- demo容器里的代码被称为【Vue模板】
- Vue实例和容器是一一对应的
- 真实开发中只有一个Vue实例,并且会配合着组件一起使用
- {{xxx}}是Vue的语法:插值表达式,{{xxx}}可以读取到data中的所有属性
- 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新(Vue实现的响应式)
<!-- 准备好一个容器 --> | |
<div id="demo"> | |
<h>Hello,{{name.toUpperCase()}},{{address}}</h1> | |
</div> | |
<script type="text/javascript" > | |
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 | |
//创建Vue实例 | |
new Vue({ | |
el:'#demo', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。 | |
data:{ //data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。 | |
name:'hello,world', | |
address:'北京' | |
} | |
}); | |
</script> |
模板语法
(1)插值语法:
功能:用于解析标签体内容
写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性
(2)指令语法:
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)
举例:v-bind:href=“xxx” 或 简写为
:href=“xxx”,xxx同样要写js表达式,且可以直接读取到data中的所有属性
<div id="root"> | |
<h>插值语法</h1> | |
<h>你好,{{name}}</h3> | |
<hr/> | |
<h>指令语法</h1> | |
<!-- 这里是展示被Vue指令绑定的属性,引号内写的是js表达式 --> | |
<a :href="school.url.toUpperCase()" rel="external nofollow" x="hello">点我去{{school.name}}学习</a> | |
<a :href="school.url" rel="external nofollow" x="hello">点我去{{school.name}}学习</a> | |
</div> | |
<script> | |
new Vue({ | |
el:'#root', | |
data:{ | |
name:'jack', | |
school:{ | |
name:'百度', | |
url:'http://www.baidu.com', | |
} | |
} | |
}) | |
</script> |
数据绑定
(1)单向绑定(v-bind):数据只能从data流向页面
(2)双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
1.双向绑定一般都应用在表单类元素上(如:input、select等)
2.v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值
<div id="root"> | |
<!-- 普通写法 单向数据绑定 --> | |
单向数据绑定:<input type="text" v-bind:value="name"><br/> | |
双向数据绑定:<input type="text" v-model:value="name"><br/> | |
<!-- 简写 v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值--> | |
单向数据绑定:<input type="text" :value="name"><br/> | |
双向数据绑定:<input type="text" v-model="name"><br/> | |
</div> | |
<script> | |
new Vue({ | |
el:'#root', | |
data:{ | |
name:'jack', | |
} | |
}) | |
</script> |
el与data的两种写法
(1)el有2种写法
- new Vue时候配置el属性
- 先创建Vue实例,随后再通过vm.$mount(‘#root’)指定el的值
<script> | |
// 第一种 | |
const vm = new Vue({ | |
el:'#root', | |
data:{ | |
name:'jack', | |
} | |
}) | |
// 第二种 | |
vm.$mount('#root') | |
</script> |
(2)data有2种写法
- 对象式
- 函数式
在组件中,data必须使用函数式
<script> | |
new Vue({ | |
el:'#root', | |
// 第一种 | |
data:{ | |
name:'jack', | |
} | |
// 第二种 | |
data() { | |
return { | |
name: 'jack' | |
} | |
} | |
}) | |
</script> |
Vue中的MVVM
- M:模型(Model) :data中的数据
- V:视图(View) :模板代码
- VM:视图模型(ViewModel):Vue实例
数据代理
了解数据代理需要js的一些知识:Object.defineProperty(),属性标志,属性描述符,getter,setter
属性标志:
对象属性(properties),除 value 外,还有三个特殊的特性(attributes),也就是所谓的“标志”
- writable — 如果为 true,则值可以被修改,否则它是只可读的
- enumerable — 如果为 true,则表示是可以遍历的,可以在for… .in Object.keys()中遍历出来
- configurable — 如果为 true,则此属性可以被删除,这些特性也可以被修改,否则不可以
Object.getOwnPropertyDescriptor(obj, propertyName)
这个方法是查询有关属性的完整信息 obj是对象, propertyName是属性名
let user = { | |
name: "John" | |
}; | |
let descriptor = Object.getOwnPropertyDescriptor(user, 'name'); | |
console.log(descriptor) | |
/* 属性描述符: | |
{ | |
"value": "John", | |
"writable": true, | |
"enumerable": true, | |
"configurable": true | |
} | |
*/ |
Object.defineProperty(obj, prop, descriptor)
obj:要定义属性的对象。
prop:要定义或修改的属性的名称
descriptor:要定义或修改的属性描述符
let user = { | |
name: "John" | |
}; | |
Object.defineProperty(user, "name", { | |
writable: false | |
}); | |
user.name = "Pete"; | |
// 打印后还是显示 'John',无法修改name值 |
其他的属性标志就不演示了,接下来看重点:访问器属性。
访问器属性:
本质上是用于获取和设置值的函数,但从外部代码来看就像常规属性。
访问器属性由 “getter” 和 “setter” 方法表示。在对象字面量中,它们用 get 和 set 表示:
let obj = { | |
get name() { | |
// 当读取 obj.propName 时,getter 起作用 | |
}, | |
set name() { | |
// 当执行 obj.name = value 操作时,setter 起作用 | |
} | |
} |
更复杂一点的使用
let user = { | |
surname: 'gao', | |
name: 'han' | |
get fullName() { | |
return this.name + this.surname; | |
} | |
} | |
console.log(user.fullName) |
从外表看,访问器属性看起来就像一个普通属性。这就是访问器属性的设计思想。我们不以函数的方式 调用 user.fullName,我们正常 读取 它:getter 在幕后运行。
截至目前,fullName 只有一个 getter。如果我们尝试赋值操作 user.fullName=,将会出现错误:
user.fullName = "Test"; // Error(属性只有一个 getter)
为 user.fullName 添加一个 setter 来修复它:
let user = { | |
surname: 'gao', | |
name: 'han' | |
get fullName() { | |
return this.name + ' ' + this.surname; | |
} | |
set fullName(value) { | |
// 这个用到了新语法 结构赋值 | |
[this.surname, this.name] = value.split(' '); | |
} | |
} | |
user.fullName = 'Li Hua' | |
console.log(user.name); | |
console.log(user.surname); |
数据代理:
数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
例: | |
let obj = { | |
x: | |
} | |
let obj = { | |
y: | |
} |
我们想要访问 **obj** 中的 **x** 的值,但我们最好不要直接去访问 **obj** ,而是想要通过 **obj2** 这个代理对象去访问。
这时候就可以用上 Object.defineProperty(),给 obj2 添加访问器属性(也就是getter和setter)
代码
let obj = { | |
x: | |
} | |
let obj = { | |
y: | |
} | |
Object.defineProperty(obj, 'x', { | |
get() { | |
return obj.x; | |
}, | |
set(value) { | |
obj.x = value; | |
} | |
}) |
Vue中的数据代理
Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)
Vue中数据代理的好处:更加方便的操作data中的数据
基本原理:
- 通过Object.defineProperty()把data对象中所有属性添加到vm上。
- 为每一个添加到vm上的属性,都指定一个getter/setter。
- 在getter/setter内部去操作(读/写)data中对应的属性。
<!-- 准备好一个容器--> | |
<div id="root"> | |
<h>学校名称:{{name}}</h2> | |
<h>学校地址:{{address}}</h2> | |
</div> | |
<script> | |
const vm = new Vue({ | |
el: '#root', | |
data: { | |
name: '浙江师范大学', | |
address: '浙江金华' | |
} | |
}) | |
</script> |
我们在控制台打印 new 出来的 vm
可以看到,写在配置项中的 data 数据被 绑定到了 vm 对象上,我先来讲结果,是 Vue 将 _data 中的 name,address 数据 代理到 vm 本身上。
先来解释下_data 是啥, _data 就是 vm 身上的 _data 属性,就是下图那个
这个 _data 是从哪来的?
<script> | |
const vm = new Vue({ | |
el: '#root', | |
// 我们在Vue 初始化的配置项中写了 data 属性。 | |
data: { | |
name: '浙江师范大学', | |
address: '浙江金华' | |
} | |
}) | |
</script> |
new Vue 时, Vue 通过一系列处理, 将匹配项上的 data 数据绑定到了 _data 这个属性上,并对这个属性进行了处理(数据劫持),但这个属性就是来源于配置项中的 data,我们可以来验证一下。
<script> | |
let data = { | |
name: '浙江师范大学', | |
address: '浙江金华' | |
} | |
const vm = new Vue({ | |
el: '#root', | |
// 我们在Vue 初始化的配置项中写了 data 属性。 | |
data: data | |
}) | |
</script> |
这一切都是通过 Object.defineProperty() 来完成的,我来模拟一下这个过程
Object.defineProperty(vm, 'name', { | |
get() { | |
return vm._data.name; | |
}, | |
set(value) { | |
vm._data.name = value | |
} | |
}) |
在插值语法中,{{ name }} 取到的值就相当于 {{ vm.name }},不用数据代理的话,在插值语法就要这样去写了。
事件处理
事件的基本使用:
- 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名
- 事件的回调需要配置在methods对象中,最终会在vm上
- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象
<!-- 准备好一个容器--> | |
<div id="root"> | |
<h>欢迎来到{{name}}学习</h2> | |
<!-- <button v-on:click="showInfo">点我提示信息</button> --> | |
<button @click="showInfo">点我提示信息1(不传参)</button> | |
<!-- 主动传事件本身 --> | |
<button @click="showInfo($event,66)">点我提示信息2(传参)</button> | |
</div> | |
<script> | |
const vm = new Vue({ | |
el:'#root', | |
data:{ | |
name:'vue', | |
}, | |
methods:{ | |
// 如果vue模板没有写event,会自动传 event 给函数 | |
showInfo(event){ | |
// console.log(event.target.innerText) | |
// console.log(this) //此处的this是vm | |
alert('同学你好!') | |
}, | |
showInfo(event,number){ | |
console.log(event,number) | |
// console.log(event.target.innerText) | |
// console.log(this) //此处的this是vm | |
alert('同学你好!!') | |
} | |
} | |
}); | |
</script> |
Vue中的事件修饰符
- prevent:阻止默认事件(常用)
- stop:阻止事件冒泡(常用)
- once:事件只触发一次(常用)
<div id="root"> | |
<h>欢迎来到{{name}}学习</h2> | |
<!-- 阻止默认事件(常用) --> | |
<a href="http://www.baidu.com" rel="external nofollow" @click.prevent="showInfo">点我提示信息</a> | |
<!-- 阻止事件冒泡(常用) --> | |
<div class="demo" @click="showInfo"> | |
<button @click.stop="showInfo">点我提示信息</button> | |
<!-- 修饰符可以连续写 --> | |
<!-- <a href="http://www.atguigu.com" rel="external nofollow" @click.prevent.stop="showInfo">点我提示信息</a> --> | |
</div> | |
<!-- 事件只触发一次(常用) --> | |
<button @click.once="showInfo">点我提示信息</button> | |
</div> |