Vue学习
vue第一个案例
vue.js 开发版本
vue.min.js 生产版本(压缩版)
1、第一个案例
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript" src="./js/vue.js" ></script> </head> <body> <div id="root"> hello world! {{name}} </div> <script type="text/javascript" > new Vue({ el: '#root', data:{ name: "郭大帅" } }) </script> </body> </html>
注意:
1.容器和VUE实例是一对一的关系。
2. {{}}双括号里面只能写js表达式和js语句,比如{{Date.now()}}
3. root容器中的代码成为模板
2、插值语法和指令语法
插值语法:通常用于指定标签体内容(起始标签到结束标签中间的内容)
指令语法:用于解析标签(标签的属性、标签体内容、绑定事件等),v-bind是其中的一种案例
案例:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript" src="./js/vue.js" ></script> </head> <body> <div id="root"> <!-- 插值语法--> hello world! {{name}} <hr/> <h1>指令语法</h1> //插值语法通常用于指定标签体内容(起始标签到结束标签中间的内容) <a v-bind:href="url" v-bind:x="hello">百度测试test</a><br> //指令语法:用于解析标签(标签的属性、标签体内容、绑定事件等),v-bind是其中的一种案例 <!-- 简写--> <a :href="url" :x="hello.toUpperCase()">百度测试test</a> </div> <script type="text/javascript" > new Vue({ el: '#root', data:{ name: "郭大帅", url:"https://www.baidu.com", hello:"testing" } }) </script> </body> </html>
3、数据绑定
VUE有两种数据绑定方式:
(1)单向数据绑定:数据只能从data流向页面(v-bind)
(2)双向数据绑定:数据不仅可以从data流向页面,还可以从页面流向data流。(v-model)
需要注意的是:
a. 双向数据绑定只能用在表单类元素中(入input,select)
b. v-model:value 可以简写成v-model,因为v-model默认收集的就是value的数据。
案例:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="./js/vue.js" ></script> <title>Document</title> </head> <body> <div id="root" > <h1>简单写法</h1> 单向数据绑定: <input type="text" v-bind:value="name"><br> 双向数据绑定: <input type="text" v-model:value="name"> <h1>缩写写法</h1> 单向数据绑定: <input type="text" :value="name"><br> 双向数据绑定: <input type="text" v-model="name"> <!-- 如下语法是错误的,因为v-model只能用在表单类的数据中 --> <!-- <h2 v-model:x="name">测试</h2>--> </div> <script type="text/javascript"> new Vue({ el:"#root", data:{ name:"我是一个文本框呀!" } }) </script> </body> </html>
4、el和data的两种写法
el第一种写法:在new Vue()说明el的属性
<body> <div id="root" > hello, world, {{name}} </div> <script type="text/javascript"> const v = new Vue({ el:"#root", data:{ name:"我是测试" } }) //console.log(v) </script> </body>
el第二种会更加灵活,先创建Vue实例,然后使用mount去挂载el
<body> <div id="root" > hello, world, {{name}} </div> <script type="text/javascript"> const v = new Vue({ //el:"#root", data:{ name:"我是测试" } }) console.log(v) v.$mount('#root') </script> </body>
data的第一种写法:对象式
<body> <div id="root" > hello, world, {{name}} </div> <script type="text/javascript"> const v = new Vue({ //el:"#root", data:{ name:"我是测试" } }) console.log(v) v.$mount('#root') </script> </body>
data的第二种写法:函数式
<body>
<div id="root" >
hello, world, {{name}}
</div>
<script type="text/javascript">
const v = new Vue({
//el:"#root",
data:function () {
//此处的this是Vue实例对象,注意不能写成箭头函数()=>{}
console.log(this)
return{
name: "我是测试"
}
}
})
console.log(v)
v.$mount('#root')
</script>
</body>
当然也可以简写成:
const v = new Vue({ //el:"#root", data() { //此处的this是Vue实例对象,注意不能写成箭头函数()=>{} console.log(this) return{ name: "我是测试" } } })
5、理解MVVM
M:模型Model:对应data中的数据
V:视图View:模版(对应el挂载的dom)
VM:视图模型(ViewModel):View实例对象
注意:
1、data中的数据会被挂载到viewModel(视图模型)中
2、ViewModel(视图模型)中的数据也可以显示在view(视图中)
例如:
<body> <div id="root" > <h2>学校:{{school}}</h2> <h2>地址:{{address}}</h2> <h2>测试1:{{$options}}</h2> <h2>测试2:{{$emit}}</h2> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", data:{ school:"咸宁职业技术学院", address:"咸宁大道" } }) console.log(vm) </script> </body>
6、数据代理-Object.defineProperty()
Object.defineProperty()
的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性
Object.defineProperty(obj, prop, desc)
- obj 需要定义属性的当前对象
- prop 当前需要定义的属性名
- desc 属性描述符
例如:
<script type="text/javascript"> let person = { name: "张三", sex: '男' } Object.defineProperty(person, 'age', { value: 18 }) console.log(person) </script>
通过Object.defineProperty()定义属性默认不可枚举,需要设置enumerable值为true。
<script type="text/javascript">
let person1 = {
name: "张三",
sex: '男',
age: 18
}
for (let key in person1) {
console.log("1----value:" + person1[key])
}
//Object.keys:将对象的属性转化为数组
console.log("person1: " + Object.keys(person1))
let person2 = {
name: "张三",
sex: '男'
}
Object.defineProperty(person2, 'age', {
value: 18
})
for (let key in person2) {
console.log("2----value:" + person2[key])
}
//Object.keys:将对象的属性转化为数组
console.log("person2: " + Object.keys(person2))
let person3 = {
name: "张三",
sex: '男'
}
Object.defineProperty(person3, 'age', {
value: 18,
enumerable: true //控制属性是否可枚举,默认是false
})
for (let key in person3) {
console.log("3----value:" + person3[key])
}
//Object.keys:将对象的属性转化为数组
console.log("person3: " + Object.keys(person3))
</script>
同时通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性。例如:
Object.defineProperty(person3, 'age', { value: 18, enumerable: true, //控制属性是否可枚举,默认是false writable:true, //控制属性是否可以被修改,默认是false configurable: true //控制属性是否可以删除,默认是false })
let number = 18;
let person3 = {
name: "张三",
sex: '男',
age: number
}
Object.defineProperty(person3, 'age', {
//当有人读取person3的age属性时(number),就会调用get函数,获取最新的
get(){
return number;
},
//当有人修改了person3的age属性时(number),就会调用set函数,且会收到具体的值
set(value){
console.log("有人修改了age值, 具体值是:" + value);
number = value;
}
})
数据代理:
Vue中的数据代理:通过vm对象(VM)来代理data对象(MODEL)中的属性操作,以此来达到更加方便操作data的目的。
原理:通过Object.defineProperty()方法将data中的数据加入到vm对象中,然后在vm相应的数据上添加get和set方法,通过get和set方法去读取和修改data中的数据。
7、事件
鼠标点击事件处理
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="./js/vue.js"></script> <title>Document</title> </head> <body> <div id="root"> <button v-on:click="showInfo">点我提示信息1</button> <hr/> <!--简写形式--> <button @click="showInfo">点我提示信息2</button> <hr/> <!--传参数形式,使用括号传参,同时如果要用event的话,使用$event作为标记传递进去--> <button @click="showInfo2($event, 888)">点我提示信息3</button> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", methods:{ //函数最终还是出现在vm上,不做数据代理 //第一个参数是事件本身信息,可以通过target拿到标签信息 showInfo(a){ console.log(a.target) //<button>点我提示信息</button> console.log(a.target.innerHTML) //点我提示信息 console.log(this == vm) //结果为true,this是vue实例,注意,若写成箭头函数,this就是window对象了 }, showInfo2(event, b){ console.log(event.target) //<button>点我提示信息</button> console.log(event.target.innerHTML) //点我提示信息 console.log(b) //结果为true,this是vue实例,注意,若写成箭头函数,this就是window对象了 } } }) </script> </body> </html>
事件修饰符,事件修饰符有如下几个:
1、prevent:阻止默认行为(常用)
2、stop:阻止事件冒泡(常用)
3、once:事件只触发一次(常用)
4、capture:使用事件的捕获模式
5、self:只有event.target是当前操作元素时才触发。
6、passive:事件的默认行为立即执行,无需等待事件的回调。
事件修饰符可以连着写,通过逗号隔开,需要注意执行的顺序。
(1) prevent
例如:某些时候想阻止a标签的跳转行为,可以使用preventDefault来阻止跳转。
<div id="root"> <a href="https://www.baidu.com" @click="showInfo">测试</a> <hr/> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", methods:{ showInfo(event){ event.preventDefault() //阻止a标签默认行为,即点击后跳转 console.log(event.target) //点我提示信息 } } }) </script>
也可以简写成如下形式
<body> <div id="root"> <a href="https://www.baidu.com" @click.prevent="showInfo">测试</a> <hr/> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", methods:{ showInfo(event){ console.log(event.target) //点我提示信息 } } }) </script>
(2) stop 阻止事件冒泡
什么是事件冒泡:在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或事件返回true,那么这个事件会向这个对象的的父级传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者到达了对象层次的最顶层,即document对象。
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="./js/vue.js"></script> <title>Document</title> </head> <style> .content{ height: 50px; background: burlywood; } </style> <body> <div id="root"> <div class="content" @click="showInfo"> <a href="https://www.baidu.com" @click.prevent="showInfo">测试</a> </div> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", methods:{ showInfo(){ alert("5666") //点我提示信息 } } }) </script> </body> </html>
阻止事件冒泡如下:
方式一:在vm的methods中函数的事件控制中加入stopPropagation控制:
const vm = new Vue({ el:"#root", methods:{ showInfo(event){ event.stopPropagation() alert("5666") //点我提示信息 } } })
方式二:通过vue修饰控制;注意要写到最里面的事件上。
<style> .content{ height: 50px; background: burlywood; } </style> <body> <div id="root"> <div class="content" @click="showInfo"> <a href="https://www.baidu.com" @click.stop="showInfo">测试</a> </div> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", methods:{ showInfo(event){ alert("5666") //点我提示信息 } } }) </script> </body>
(3)once:事件只触发一次(常用)
键盘事件
1、Vue中常见的键盘别名
(1)回车=》enter
(2)删除=》delete(按下删除或退格键触发)
(3)退出=》esc
(4)空格=》space
(5)换行=》tab(特殊,必须与keydown配合使用,不是keyup)
(6)上=》up
(7)下=》down
(8)左=》left
(9)右=》right
案例如下:按下回车键在控制台显示文本框中输入的内容
方式一:不使用Vue中的键盘别名:
<head> <meta charset="UTF-8"> <script type="text/javascript" src="./js/vue.js"></script> <title>Document</title> </head> <body> <div id="root"> <h1>test</h1> <input type="text" placeholder="按下回车提示输入" @keyup="showInfo"> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", methods:{ showInfo(event){ //event.keyCode表示当前按下键盘对应键的编码 if(event.keyCode != 13){ return; } console.log(event.target.value); } } }) </script> </body>
方式二:使用Vue中的enter别名
<head> <meta charset="UTF-8"> <script type="text/javascript" src="./js/vue.js"></script> <title>Document</title> </head> <body> <div id="root"> <h1>test</h1> <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo"> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", methods:{ showInfo(event){ console.log(event.target.value); } } }) </script> </body>j
几个特殊按键:ctrl、alt、shift、meta键(win键)是系统修饰键,若将keyup与这几个键一起配合使用,在按下修饰键的同时,需要再按一下其他键,随后释放其他键,事件才触发。只有与keydown配合使用,才正常触发事件。
8、计算属性
1. computed 阐述
(1)监听值未在data中定义,以return返回值形式;
(2)计算属性变量在computed中定义,属性监听在data中定义。
(3)计算属性默认只有get来读取,手动修改计算属性时,会触发手写的set函数。
(4)计算属性的值会被缓存,只有实例中相关依赖值改变时,才重新计算,性能好但不适合做异步请求。
(5)计算属性是声明式的描述一个值依赖了其他值,依赖的值改变后重新计算结果更新DOM。属性监听的是定义的变量,当定义的值发生变化时,执行相对应的函数。
<html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="./js/vue.js"></script> <title>Document</title> </head> <body> <div id="root"> 姓:<input type="text" v-model="firstName" /> <br/> <br/> 名:<input type="text" v-model="lastName" /> <br/> <br/> 姓名:<span>{{fullName}}</span> 姓名:<span>{{fullName}}</span> 姓名:<span>{{fullName}}</span> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", data: { firstName: "张", lastName: "三" }, computed:{ fullName:{ //当有人读取fullName的时候,get就会被调用,返回值就作为fullName的值。 //get什么时候调用,(1)初次调用fullName的时候,(2)所依赖的数据发生变化的时候。 get(){ console.log("get......"); return this.firstName + "_" + this.lastName; }, //当fullName被修改的时候,调用set方法 set(value){ console.log("set......"); const arr = value.split('-'); this.firstName = arr[0]; this.lastName = arr[1]; } } } }) </script> </body> </html>
9. 监视属性
写在Vue对象的watch
中,它的值是配置对象——即属性名
当被监听的属性改变时,回调函数自动调用,进行相关操作
监视的属性必须存在,才能进行监视
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="./js/vue.js"></script> <title>Document</title> </head> <body> <div id="root"> <h1>监视属性</h1> <h2>今天天气很{{info}}</h2><br/> <input type="button" value="点击更换天气" @click="change"/> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", data: { isHot: true }, computed:{ info(){ return this.isHot ? "炎热" : "凉爽" ; } }, methods:{ change(){ this.isHot = !this.isHot; } } watch:{ info:{ immediate: true, //初始化时,让handler调用一下 //当isHot发生变化的时候,handler被调用,参数可以带,也可以不带 handler(newValue, oldValue){ console.log("新值:" + newValue); console.log("旧值:" + oldValue); } } } }) </script> </body> </html>
对象的深度监视
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="./js/vue.js"></script> <title>Document</title> </head> <body> <div id="root"> <h1>深度监视属性</h1> <h2>a的值是:{{numbers.a}}</h2><br/> <input type="button" value="a+1" @click="addA"/> <h2>b的值是:{{numbers.b}}</h2><br/> <input type="button" value="b+1" @click="addB"/> </div> <script type="text/javascript"> const vm = new Vue({ el:"#root", data: { numbers:{ a: 10, b: 100 } }, methods:{ addA(){ this.numbers.a++; }, addB(){ this.numbers.b++; } }, //watch默认不监控对象内部数据的变化(只监视最外层) //若想监视多层(对象内部的属性),需要配置deep:true watch:{ numbers:{ deep:true, handler(){ console.log("test...."); } } } }) </script> </body> </html>
计算属性和监听属性的区别
(1)计算属性 以return返回值形式;监听属性以脚本的形式去更新值;
(2)计算属性可以完成的,监听属性也都可以完成。监听属性可以完成的,计算属性不一定能完成,例如异步操作。
两个最小原则:
(1)Vue管理的函数最好写成普通函数,这样this才指向vm。
(2)不被vue管理的函数(定时器回调函数,ajax回调函数,Promise回调函数)都要写成箭头函数,这样才可以被vue托管。