目录
5.只有event.target是当前操作的元素时才触发事件
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕
Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名
Vue简介
Vue是现代前端开发中非常受欢迎的框架之一,它的以下特点让他不仅在开发体验、更在性能方面表现优异。
渐进式框架
Vue 是渐进式的,我们可以根据需求逐步引入想要的功能。
双向数据绑定
Vue.js 提供了类似于 Angular 的双向数据绑定机制,确保了数据和页面的自动同步。
组件化
Vue.js 是基于组件构建的,我们可以通过创建和复用组件来构建复杂的 UI 界面。每个组件都有其独立的逻辑、样式和视图。
虚拟 DOM
Vue.js 使用虚拟 DOM 技术来提高性能。通过对比虚拟 DOM 中的差异,只对真正发生变化的部分进行更新,从而减少不必要的 DOM 操作。
指令系统
Vue 提供了一些内置指令(如 v-if
、v-for
、v-model
等),简化了对 DOM 的操作。
简单上手
下载引用
首先需要下载Vue.js,可以在Vue官网下载vue.js以及vue.min.js。随后直接在需要的页面中引入js即可。注意:在开发时不要使用压缩版本,否则会没有报错提示和警告。
vue.js devtools
我们可以在浏览器的插件商店中下载vue.js devtools。这个插件可以让我们清晰的看到页面中的Vue结构,并且可以直接通过这个插件对Vue数据进行测试修改,观察页面的变化。
正式使用
<div id="demo">
<h1>你好,{{name}},欢迎来到{{address}}</h1>
</div>
<script type="text/javascript" >
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
//创建Vue实例
new Vue({
el:'#demo', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。
data:{ //data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。
name:'jack',
address:'北京'
}
})
</script>
效果图:
小结:
- 容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
- root容器里的代码被称为【Vue模板】
- Vue实例和容器是一一对应的(不能一对多或者多对一)
- 真实开发中只有一个Vue实例,并且会配合着组件一起使用;
- 双大括号中要写js表达式,其中的内容可以自动读取到data中的所有属性
- 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新
模板语法
Vue的模板语法有两大类:
插值语法
功能:用于解析标签体内容。
写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
指令语法
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件.....)。
举例:v-bind:href="xxx" 或 简写为 :href="xxx",xxx同样要写js表达式,
且可以直接读取到data中的所有属性。
示例:
<div id="root">
<h1>插值语法</h1>
<h3>你好,{{name}}</h3>
<hr/>
<h1>指令语法</h1>
<a v-bind:href="obj.url">{{obj.name}}一下,你就知道</a>
<a :href="obj.url">{{obj.name}}一下,你就知道</a>
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'jack',
obj:{// data中也可以有对象
name:'百度',
url:'http://www.baidu.com',
}
}
})
</script>
效果:
数据绑定
Vue中有2种数据绑定的方式:
单向绑定(v-bind)
数据只能从data流向页面
双向绑定(v-model)
数据不仅能从data流向页面,还可以从页面流向data
- 双向绑定只能应用在表单类元素上(如:input、select等)
- 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/> -->
<!-- 简写 -->
单向数据绑定:<input type="text" :value="name"><br/>
双向数据绑定:<input type="text" v-model="name"><br/>
<!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)上 -->
<!-- <h2 v-model:x="name">你好啊</h2> -->
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'尚硅谷'
}
})
</script>
效果:
修改了双向绑定的input中的value之后,单项绑定的也会跟着改变,那是因为双向绑定的input不仅改变了页面里的数据,同时还更改了data里的name,而一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新。
el与data的两种写法
el的两种写法
- new Vue时候配置el属性。
- 先创建Vue实例,随后再通过vm.$mount('#root')指定el的值
data的两种写法
- 对象式
- 函数式
使用组件时,data必须使用函数式,否则会报错。
由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了
<div id="root">
<h1>你好,{{name}}</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
//el的两种写法
/* const v = new Vue({
//el:'#root', //第一种写法
data:{
name:'jack'
}
})
console.log(v)
v.$mount('#root') //第二种写法 */
//data的两种写法
new Vue({
el:'#root',
//data的第一种写法:对象式
/* data:{
name:'jack'
} */
//data的第二种写法:函数式
data(){
console.log('@@@',this) //此处的this是Vue实例对象
return{
name:'jack'
}
}
})
</script>
Vue中的数据代理
通过vm对象来代理data对象中属性的操作(读/写)
作用
可以更加方便的操作data中的数据
基本原理
- 通过Object.defineProperty()把data对象中所有属性添加到vm上。
- 为每一个添加到vm上的属性,都指定一个getter/setter。
- 在getter/setter内部去操作(读/写)data中对应的属性。
输出vm可以发现,data中每个数据都有对应的getter和setter
事件处理
基本使用
- 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
- 事件的回调需要配置在methods对象中,最终会在vm上;
- methods中配置的函数,不要用箭头函数!否则this就不是vm了;
- @click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;
<div id="root">
<h2>你好,{{name}}</h2>
<!-- <button v-on:click="showInfo">点我提示信息</button> -->
<button @click="showInfo1">点我提示信息1(不传参)</button>
<button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
name:'jack',
},
methods:{
showInfo1(event){
// console.log(event.target.innerText)
// console.log(this) //此处的this是vm
alert('同学你好!')
},
showInfo2(event,number){
console.log(event,number)
// console.log(event.target.innerText)
// console.log(this) //此处的this是vm
alert('同学你好!!')
}
}
})
</script>
效果:
点击第一个按钮只有alert信息
点击第二个,alert同时还会输出点击事件和66
事件修饰符
- prevent:阻止默认事件(常用)
- stop:阻止事件冒泡(常用)
- once:事件只触发一次(常用)
- capture:使用事件的捕获模式
- self:只有event.target是当前操作的元素时才触发事件
- passive:事件的默认行为立即执行,无需等待事件回调执行完毕
以下的代码都是对于同一个vue实例以及样式表:
<style>
* {
margin-top: 20px;
}
.demo1 {
height: 50px;
background-color: skyblue;
}
.box1 {
padding: 5px;
background-color: skyblue;
}
.box2 {
padding: 5px;
background-color: orange;
}
.list {
width: 200px;
height: 200px;
background-color: peru;
overflow: auto;
}
li {
height: 100px;
}
</style>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el: '#root',
data: {
name: '尚硅谷'
},
methods: {
showInfo(e) {
alert('同学你好!')
// console.log(e.target)
},
showMsg(msg) {
console.log(msg)
},
demo() {
for (let i = 0; i < 100000; i++) {
console.log('#')
}
console.log('累坏了')
}
}
})
</script>
1.阻止默认事件
<!-- 阻止默认事件(常用) -->
<a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息</a>
点击后只有提示信息,不会跳转页面
2. 阻止冒泡
<!-- 阻止事件冒泡(常用) -->
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息</button>
</div>
只会弹出一个alert,因为冒泡事件被阻止,如果不阻止则会有两个alert(一个button绑定de ,一个外层div绑定的)
3.事件只触发一次
<!-- 事件只触发一次(常用) -->
<button @click.once="showInfo">点我提示信息</button>
只有第一次点击有效,以后的点击将不会有alert
4.开启捕获模式
<!-- 使用事件的捕获模式 -->
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">
div2
</div>
</div>
开启了事件的捕获模式,点击box2时先触发box1的绑定事件,后触发box2的绑定事件
5.只有event.target是当前操作的元素时才触发事件
<!-- 只有event.target是当前操作的元素时才触发事件; -->
<div class="demo1" @click.self="showInfo">
<button @click="showInfo">点我提示信息</button>
</div>
点击button只会触发button的绑定事件,demo1的绑定事件不会被触发,只有真正点击demo1时才会触发
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕
<!-- 事件的默认行为立即执行,无需等待事件回调执行完毕; -->
<ul @wheel.passive="demo" class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
滚动滚轮时,页面立即下滑,不会等待循环结束
7.修饰符的连写
<div class="demo1" @click="showInfo">
<!-- 修饰符可以连续写 -->
<a href="http://www.atguigu.com" @click.prevent.stop="showInfo">点我提示信息</a>
</div>
同时实现了stop和prevent的功能
键盘事件
Vue中常用的按键别名:
- 回车 => enter
- 删除 => delete (捕获“删除”和“退格”键)
- 退出 => esc
- 空格 => space
- 换行 => tab (特殊,必须配合keydown去使用)
- 上 => up
- 下 => down
- 左 => left
- 右 => right
Vue未提供别名的按键
可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
系统修饰键(用法特殊
ctrl、alt、shift、meta
配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
配合keydown使用:正常触发事件。
也可以使用keyCode去指定具体的按键(不推荐)
Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名
示例
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInfo">
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
Vue.config.keyCodes.huiche = 13 //定义了一个别名按键
new Vue({
el:'#root',
data:{
name:'尚硅谷'
},
methods: {
showInfo(e){
// console.log(e.key,e.keyCode)
console.log(e.target.value)
}
},
})
</script>
计算属性
定义
要用的属性不存在,要通过已有属性计算得来。
原理
底层借助了Objcet.defineproperty方法提供的getter和setter。
优势
与直接使用methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
备注
- 计算属性最终会出现在vm上,直接读取使用即可。
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
示例
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
computed:{
fullName:{
//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
//get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
get(){
console.log('get被调用了')
// console.log(this) //此处的this是vm
return this.firstName + '-' + this.lastName
},
//set什么时候调用? 当fullName被修改时。
set(value){
console.log('set',value)
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
</script>
简写
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
},
computed:{ //简写
fullName(){
console.log('get被调用了')
return this.firstName + '-' + this.lastName
}
}
})
</script>
直接在计算属性中写入getter即可,不能有setter,既只有确定以后不会对数据进行修改时才能使用简写
监视属性
当被监视的属性变化时, 回调函数自动调用, 进行相关操作。监视的属性必须存在,才能进行监视
监视的两种写法
- new Vue时传入watch配置
- 通过vm.$watch监视
示例
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
/* watch:{
isHot:{
immediate:true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}
} */
})
vm.$watch('isHot',{
immediate:true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
})
</script>
输出的第一行是打开了immediate之后直接输出的,没有旧值则输出undefined
深度监视
Vue中的watch默认不监测对象内部值的改变(一层)。
配置deep:true可以监测对象内部值改变(多层)。
Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
使用watch时根据数据的具体结构,决定是否采用深度监视。
简写
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
//简写
/* isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
} */
}
})
//简写
vm.$watch('isHot',(newValue,oldValue)=>{
console.log('isHot被修改了',newValue,oldValue,this)
})
</script>
只有不开启immediate以及深度监视时才可用简写,直接将handler的内容写在watch中
绑定样式
class样式
class="xxx" xxx可以是字符串、对象、数组。
- 字符串写法适用于:类名不确定,要动态获取。
- 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
- 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
stule样式
- :style="{fontSize: xxx}"其中xxx是动态值。
- :style="[a,b]"其中a、b是样式对象。
示例
样式
<style>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy{
border: 4px solid red;;
background-color: rgba(255, 255, 0, 0.644);
background: linear-gradient(30deg,yellow,pink,orange,yellow);
}
.sad{
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
.normal{
background-color: skyblue;
}
.atguigu1{
background-color: yellowgreen;
}
.atguigu2{
font-size: 30px;
text-shadow:2px 2px 10px red;
}
.atguigu3{
border-radius: 20px;
}
</style>
html,js
<div id="root">
<!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div> <br/><br/>
<!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
<div class="basic" :class="classArr">{{name}}</div> <br/><br/>
<!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
<div class="basic" :class="classObj">{{name}}</div> <br/><br/>
<!-- 绑定style样式--对象写法 -->
<div class="basic" :style="styleObj">{{name}}</div> <br/><br/>
<!-- 绑定style样式--数组写法 -->
<div class="basic" :style="styleArr">{{name}}</div>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'jack',
mood:'normal',
classArr:['style','style2','style3'],
classObj:{
style1:false,
style2:false,
},
styleObj:{
fontSize: '40px',
color:'red',
},
styleObj2:{
backgroundColor:'orange'
},
styleArr:[
{
fontSize: '40px',
color:'blue',
},
{
backgroundColor:'gray'
}
]
},
methods: {
changeMood(){
const arr = ['happy','sad','normal']
const index = Math.floor(Math.random()*3)
this.mood = arr[index]
}
},
})
</script>
效果