<script type="text/javascript" src="./js/vue.js">script>
<div id="root">
hello {{name}}
div>
<script>
// 创建Vue实例
new Vue({
el: '#root', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。
data: { //data中用于存储数据,数据供el所指定的容器去使用,data暂时先写成一个对象。
name: 'tom'
}
})
script>
总结:
1、想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象;
2、root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;
3、root容器里的代码被称为【Vue模板】;
4、Vue实例和容器是一一对应的;一个容器只能由一个Vue实例接管,
5、真实开发中只有一个Vue实例,并且会配合着组件一起使用;
{{xxx}}
,xxx是js表达式,且可以直接读取到data中的所有属性。v-xxx
<div id="root">
hello, {{stu.name.toUpperCase()}}
<br>
<a v-bind:href="url">百度a>
<a v-bind:href="url.toUpperCase()">百度a>
div>
<script>
new Vue({
el: '#root',
data: {
stu: {
name: 'tom',
age: 18
},
url: 'https://www.baidu.com/',
}
})
script>
最终页面被解析为:
注意区分:js表达式 和 js代码(语句)
写法一:new Vue的时候配置el属性。
<script>
const v = new Vue({
el: '#root', //第一种写法
data: {
name: 'tom',
}
})
script>
写法二:先创建Vue实例,随后再通过 Vue实例.$mount(‘#root’)指定el的值
<script>
const v = new Vue({
data: {
name: 'tom',
}
})
// 第二种写法
v.$mount('#root')
script>
写法一:对象式
<script>
// data的两种写法
new Vue({
el: '#root',
// 对象式
data: {
name: 'tom',
}
})
script>
写法二:函数式
<script>
new Vue({
el: '#root',
// 函数式
data: function () {
console.log(this);
return {
name: '山西'
}
}
})
// 或者简写为:
new Vue({
el: '#root',
// 函数式
data () { //不可写为箭头函数,否则this返回的不是Vue实例
console.log(this); // this返回的是vue实例
return {
name: '山西'
}
}
})
script>
data的2种写法:对象式、函数式。
如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
一个重要的原则:由Vue管理的函数 (data函数就是一个Vue管理的函数),一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了
拓展
(1) data中所有的属性,最后都出现在了vm身上。
(2) vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。
<div id="root">
姓名:{{name}}
<br>
地址:{{address}
<br>
vm属性$options{{$options}}
<br>
Vue原型{{$emit}}
div>
<script>
const vm = new Vue({
el: '#root',
data: {
name: '小白',
address: '北京'
}
})
console.log(vm);
script>
语法:Object.defineProperty(对象,属性名,配置项)
:给对象添加属性
需求1: 给person添加age属性
let obj = {
name: 'jerry',
gender: '男',
age: 10
}
let person ={
name: 'jerry',
gender: '男',
}
Object.defineProperty(person, 'age', {
value: 10,
enumerable: true, // 控制属性是否可以被枚举,默认false Object.keys(对象)
writable: true, // 控制属性是否可以被修改,默认false
configurable: true, // 控制属性是否可以被删除,默认false
});
相较于obj
,person
这种添加属性的方式可以对属性进行设置,obj
则不能设置
需求2:现有一个number数据,如何使age的值始终为number的值
let number = 10;
const person = {
name: 'tom',
gender: '男',
}
Object.defineProperty(person, 'age', {
// 当有人读取person的age属性时,get函数(一般说getter方法)就会被调用,且返回值就是age的值
get () {
console.log('读取age值');
return number
},
// 当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set (value) {
console.log('修改age值');
number = value
}
})
此外,打印person也可以发现
点击(…)时,也会调用getter方法
数据代理:通过一个对象来对另一个对象的属性进行读或写的操作。
// obj有个x,希望通过obj2对obj的x进行读取和修改
let obj = { x: 100 }
let obj2 = { y: 200 }
Object.defineProperties(obj2, 'x', {
get () {
return obj.x
},
set (value) {
obj.x = value
}
})
<div class="root">
<h2>学校名称:{{name}}h2>
<h2>学校地址:{{address}}h2>
div>
<script>
const vm = new Vue({
el: 'root',
data: {
name: '尚硅谷',
address: '北京'
}
})
script>
打印vm得知,vm身上的name
和address
都是Object.definePropterty()
加上去的
vm将data数据存在了自身的_data
中,当读取vm.address
时,通过getter方法获取Vm._data.address
的值
总结:
1、Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读、写)
2、Vue中数据代理的好处:更方便操作data中的数据,不用写_data.name
,直接写name就行。
3、基本原理:通过Object.defineProperty()
把data对象中的所有属性加到vm上,为每一个添加到vm上的属性指定getter/setter。在getter/setter内部操作(读、写)data中对应的属性
语法:v-on:xxx
或简写方式 @xxx
绑定事件,xxx是事件名
<div id="root">
<button v-on:click="showInfo1">(v-on)不传参函数button>
<button @click="showInfo2($event,66)">(@)不传参函数button>
div>
不传参的函数默认接收事件对象event
const vm = new Vue({
el: '#root',
data: {
name: 'tom'
},
methods: {
showInfo1 (event) {
console.log('showInfo1');
console.log(event);
},
showInfo2 (event, number) {
console.log(event);
console.log(number);
},
// showInfo1: (event) => {
// console.log(this); // window;指向的不是vue实例了
// }
}
})
1、阻止默认事件
Vue: prevent
----> 对应原生jsevent.preventDefault()
<div id="root">
<a href="https://www.baidu.cn" @click.prevent="moveToBaidu">点击链接跳转百度a>div>
<script>
const vm = new Vue({
...
methods: {
moveToBaidu (event) {
// event.preventDefault()
console.log('点击链接');
}
}
})
script>
2、阻止事件冒泡
Vue: stop
----> 对应原生js event.stopPropagation()
<div @click="stopBubble('div')" class="bubbleBox">
<button @click="stopBubble('btn')">点击冒泡button>
div>
<script>
const vm = new Vue({
...
methods: {
stopBubble (str) {
// event.stopPropagation();
console.log(str + '冒泡');
}
}
...
})
script>
未添加stop修饰符时,点击button,分别打印:btn冒泡 div冒泡。
添加stop修饰符后,点击button,打印:btn冒泡
<button @click.stop="stopBubble('btn')">点击冒泡button>
注:修饰符可以连写
<div @click="stopBubble('div')" class="bubbleBox">
<a href="https://www.baidu.cn" @click.stop.prevent="stopBubble('a链接')">点击链接跳转百度button>
div>
3、事件只发生一次
点击button,打印once;再点击,则不会再触发事件
<button @click.once="showOnce">点击事件只触发一次button>
<script>
const vm = new Vue({
...
methods: {
showOnce () {
console.log('once');
}
}
...
})
script>
4、事件捕获
事件流是先捕获,后冒泡。而在上述冒泡事件点击中,点击button,依次打印:btn冒泡 div冒泡。这是因为默认对冒泡事件进行响应。
若给div添加捕获模式,则依次打印:div冒泡,btn冒泡
<div @click.capture="stopBubble('div')" class="bubbleBox">
<button @click="stopBubble('btn')">点击冒泡button>
div>
keyup和keydown都是键盘按键事件。
键盘每个键都有键名和值,通过key和keycode可以获取
key <input type="text" @keydown="showKey">
<script>
const vm = new Vue({
...
methods: {
showKey (e) {
console.log(e.key,e.keycode); //打印按键
}
}
})
script>
每按一个键,都会触发一次事件。若想在按某个键(比如回车)之后再触发事件,可以在keydown/keyup后指定按键。
Vue里常用的按键别名:
enter<input type="text" @keydown.enter="showInfo"><br>
Tab<input type="text" @keydown.Tab="showInfo"><br>
<script>
const vm = new Vue({
...
methods: {
showInfo (e) {
console.log(e.target.value);
}
}
})
script>
若两个键配合使用,则:
Ctrl+y <input type="text" @keydown.ctrl.y="showInfo">
系统修饰键:ctrl、alt、shift、meta
总结: 系统修饰键配合keyup触发事件很麻烦,tab键配合keyup不起作用,因此键盘按键事件一般都用keydown,不用keyup