Vue入门到关门之指令系统
一、引入
在 Vue.js 中,指令(Directives)是一种特殊的标记,用于向 Vue 实例提供特殊的行为。指令以 v-
开头,例如 v-if
、v-for
等。
- 指令的本质就是语法糖,标志位。在编译阶段 render 函数里,会把指令编译成 JavaScript 代码。
- 注意:指令都是放在标签上的
二、指令
1、文本指令
(1)v-text
v-text
是渲染字符串,会覆盖原先的字符串
(2)v-html
v-html
是渲染为html。- 但是,不建议使用v-html指令,因为它会导致被恶意者进行XSS攻击的潜在风险。
(3)示例
{{}}
双大括号和v-text
都是输出为文本。那如果想输出为html。使用v-html
,如下例子
<div id="app"> <div>{{innerHtml}}</div> <div v-text="innerHtml">123</div> <div v-html="innerHtml">123</div> </div> <script> new Vue({ el:"#app", data:{ innerHtml:'<button>一个按钮</button>' } }) </script>
2、事件指令
(1)v-on
-
v-on 事件绑定指令,用来辅助程序员为DOM 元素绑定事件监听,并提供处理逻辑。
-
语法:
v-on:事件类型="methods中函数名"
v-on:事件类型="内联语句"
-
由于v-on 指令在开发中使用频率非常高,因此,vue 官方为其提供了简写形式(简写为英文的@)
-
常用的事件有:点击事件,双击事件,拖动事件,得到焦点,失去焦点。。。。
例如:
<body> <div id="app"> <!-- 完整写法 v-on: --> // v-on:事件名 = "methods中的函数名" <div v-on:click="handleClick">点击事件</div> // v-on:事件名 = "内联语句" <button v-on:click="count++">按钮</button> <!-- 缩写 @ --> <div @click="handleClick">点击事件</div> <button @click="count++">按钮</button> </div> </body> <script> new Vue({ el:"#app", data:{ }, methods:{ // 定义一个 点击函数 handleClick:function(){ console.dir('click event') } }, }) </script>
(2)es6的对象写法
var hobby=['抽烟','烫头'] var obj={ 'name':'lqz', // 正常写法 age:19, // 1、key之可以不用加引号 hobby, // 2、数组可以直接写名字,但必须在外面定义好 showName:function() { // 3、定义函数 console.log(this.name) }, showName() { // 4、函数简写 console.log(this.name) } } console.log(obj) obj.showName() // 外部直接调用内部函数
(3)v-on调用传参
- 函数有一个参数
- 如果在事件中触发函数,没有传参数,会自动把事件对象传入
- 定义好的参数,传的就是什么参数
- 把事件对象传入(
$event
)
- 函数有多个参数
- 少传不加括号,但是js里面的函数需要多个参数,结果是第一个是事件对象,其他为undefined
- 少传加括号,但是js里面的函数需要多个参数,不会把自动把事件对象传入,均为undefined
- 需要3个参数,但是多传了参数,结果是只接受自己的3个参数,多的不要
- 多个参数中,需要传入事件对象,方式为
$event
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./vue/vue.js"></script> <style> img { height: 300px; width: 200px; } </style> </head> <body> <div id="app"> <h1>事件指令--函数有参数</h1> <button @click="handleFunc1">不传参数-函数有参数</button> <br> <button @click="handleFunc1(isShow)">传参数-函数有参数</button> <br> <button @click="handleFunc1($event)">传参数-函数有参数-把事件对象传入</button> <br> <button @click="handleFunc2">多个参数-少传不加括号</button> <br> <button @click="handleFunc2()">多个参数-少传-加括号event不会自动传入</button> <br> <button @click="handleFunc2(1,2,3,4,5,6,)">多个参数-多传</button> <br> <button @click="handleFunc2(1,$event)">多个参数-event作为第二个参数</button> </div> </body> <script> var vm = new Vue({ el: '#app', data: { isShow:true }, methods: { handleFunc1(event){ //1 如果在事件中触发函数,没有传参数,会自动把 事件对象传入 console.log(event) }, handleFunc2(a,b,c){ console.log(a) console.log(b) console.log(c) } } }) </script> </html>
3、属性指令
(1)v-bind
v-bind 属性绑定指令,用来动态的设置html的标签属性,比如:src、url、title。。。
- 语法:
v-bind:属性名="表达式"
- 简写为
:属性名="表达式"
示例:
- 控制图片轮播
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./vue/vue.js"></script> </head> <body> <div id="app"> <button @click="toggleAutoChange">{{ isAutoChanging ? '停止' : '开始' }}自动切换美女图片</button> <img :src="currentImage" alt="Beautiful Girl"> </div> </body> <script> var vm = new Vue({ el: "#app", data: { isAutoChanging: false, images: [ "http://img.netbian.com/file/2024/0416/004850qAPxg.jpg", "http://img.netbian.com/file/2024/0411/0016435MJh0.jpg", "http://img.netbian.com/file/2024/0409/002601sxcu4.jpg", "http://img.netbian.com/file/2024/0323/001609whWN7.jpg" ], currentIndex: 0, intervalId: null }, computed: { currentImage() { return this.images[this.currentIndex]; } }, methods: { toggleAutoChange() { this.isAutoChanging = !this.isAutoChanging; if (this.isAutoChanging) { this.interval = setInterval(() => { this.currentIndex = (this.currentIndex + 1) % this.images.length; }, 1000); } else { clearInterval(this.interval); } } }, destroyed() { clearInterval(this.interval); } }) </script> </html>
- 点击按钮随机切换图片
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./vue/vue.js"></script> </head> <body> <div id="d1"> <button @click="handleChange">点我换一张</button> <br> <img :src="img_change" alt=""> </div> </body> <script> var vm = new Vue({ el: "#d1", data: { img_change: './img/1.jpg', // 图片是以数字命名的 }, methods: { handleChange: function () { this.img_change = `./img/${Math.ceil(Math.random() * this.list1.length)}.jpg` } } }) </script> </html>
(2)v-bind 对于样式控制的增强 - 操作class
语法::class=字符串/数组/对象
- class可以绑定的类型有字符串、数组、对象
var vm = new Vue({ el: '#app', data: { // 1、绑定的可以是字符串形式 str_class: 'background', // 2、绑定的也可以是数组形式(常用) list_class: ['background'], // 3、对象形式 obj_class: {'background': true, 'fontsize': false}, }, methods: { handleChangeBack1: function () { this.str_class = this.str_class + ' fontsize' }, handleChangeBack2: function () { // this.list_class.push('fontsize') this.list_class.pop('background') }, handleChangeBack3: function () { this.obj_class.fontSize = true }, }
(3)v-bind 对于样式控制的增强 - 操作style
var vm = new Vue({ el: '#app', data: { // 1、字符串形式 str_style: 'background-color: yellow', // 2、数组形式 list_style: [{'background': 'yellow'}], // 3、对象形式(更合适),一般用对象是用来修改里面的值会好一点 // obj_style: {'background-color': 'pink', 'font-size': '50px'}, // js的key可以去掉'',到那时中间有 - 的要转成驼峰 obj_style: {backgroundColor: 'pink', fontSize: '50px'}, }, methods: { handleChangeBack4: function () { this.str_style = this.str_style + ';font-size: 60px' }, handleChangeBack5: function () { // this.list_style.push({'font-size': '60px'}) this.list_style.push({'margin': 'auto'}) }, handleChangeBack6: function () { // 对象或者数组新增加的属性,vm监控不到就无法实现响应式,于是页面就没有发生变化,但是数据已经变了 // this.obj_style ['font-size'] = '90px' // 但是对象中原来有的属性,修改是能监控得到的 // this.obj_style ['background-color'] = 'yellowgreen' //这么写的话原来对象没有的值,就能监控到了--> 如果改了对象没有影响到页面--> vm没有监控到的话--> 就使用Vue.set Vue.set(this.obj_style, 'font-size', '90px') } }
(4)完整示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./vue/vue.js"></script> <style> .div1 { width: 300px; height: 300px; } .div2 { background-color: pink; } .div3 { font-size: 60px; } .div4 { margin: auto; } </style> </head> <body> <div id="app"> <h1>class属性</h1> <!-- <div :class="class_str">我</div>--> <!-- <div :class="class_list">我</div>--> <div :class="class_obj">我是div</div> <button @click="handleChange">点击变化</button> <h2>style属性</h2> <div :style="style_obj">我是div</div> <button @click="handleChange2">点击变化</button> </div> </body> <script> var vm = new Vue({ el: '#app', data: { //1 class 属性可以是字符串,数组,对象 class_str: 'div1 div2', class_list: ['div1', 'div2'], // 类用它多 class_obj: {div1: true, div2: true, div3: true, div4: false}, // //2 style 属性可以是字符串,数组,对象 style_str: 'background-color: green;height: 300px;width: 300px', style_list: [{'background-color': 'green'}, {height: '300px'}, {width: '300px'}], style_obj: {backgroundColor: 'green', height: '330px', width: '300px'} // 用的多 }, methods: { handleChange() { // 1 字符串形式 // this.class_str='div1 div2 div3 div4' // 2 数组形式,用的多,可以追加,可以删除--》样式就变化了 // this.class_list.push('div3') // 数组.push()-->返回值是 数组大小 // this.class_list.pop() // 3 对象形式 this.class_obj.div4 = true }, handleChange2() { // 1 字符串形式 // this.style_str = 'background-color: green;height: 300px;width: 300px;margin:auto' // 2 数组形式 // this.style_list.push({'margin':'auto'}) // 3 对象形式 // 换背景色 // this.style_obj['backgroundColor'] = 'pink' // 居中 // this.style_obj['margin'] = 'auto' // 对象中原来没有,后来加进去,就不会触发响应式 // 使用set解决 Vue.set(this.style_obj,'margin','auto') } } }) </script> </html>
(5)问题补充
-
如果当你改了对象,或数组,发现页面没有变化,而实际上值真正的被改了,这是为什么呢?
- 这是因为对象或者数组新增加的属性,vm监控不到就无法实现响应式,于是页面就没有发生变化,但是数据已经变了
-
解决方案:使用Vue.set
-
Vue.set(object, key, value)
object
: 要向其添加属性的目标对象。key
: 要添加的属性的键。value
: 要添加的属性的值
4、条件渲染
(1)v-if v-else-if v-else
- v-if指令,控制元素是否加载。
- v-esle-if/v-else指令不能单独使用,必须配合v-if一起使用。
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./vue/vue.js"></script> </head> <body> <div id="app"> <h1>条件判断</h1> <h2>分数是:{{score}}</h2> <h3 v-if="score>=90&&score<=100">优秀</h3> <h3 v-else-if="score>=80&&score<90">良好</h3> <h3 v-else-if="score>=60&&score<80">及格</h3> <h3 v-else>不及格</h3> </div> </body> <script> var vm = new Vue({ el: '#app', data: { score: 80 } }) </script> </html>
(2)v-show
- v-show 指令,控制元素的显示隐藏,元素存在并占据空间。
- 元素隐藏时,相当于给该元素添加了 CSS 样式:display:none;
<div v-show="show">hello vue</div> <button @click="show = !show">changeShow</button>
(3)v-if 和 v-show的区别
v-if和v-show有同样的效果,不同在于v-if
是重新渲染,而v-show
使用display
属性来控制显示隐藏。频繁切换的话使用v-show
减少渲染带来的开销。
5、列表渲染
(1)v-for
v-for 列表渲染指令,基于数据循环,多次渲染整个元素---> 数组、对象、数字。。。
语法:
<div v-for="item in items" :key="item.id"> {{ item.text }} </div>
v-for="item in items"
:这里items
是一个数组或者对象,item
是数组中的每个元素,或者对象中的每个属性值,你可以用item
来引用当前遍历的元素。:key="item.id"
:为了给 Vue 提供一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一key
属性。
示例:
如果我们有一个存储了用户信息的数组:
data: { users: [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' } ] }
我们可以使用 v-for
来循环渲染每个用户的名字:
<div v-for="user in users" :key="user.id"> {{ user.name }} </div>
这样就会生成如下 HTML 结构:
<div>Alice</div> <div>Bob</div> <div>Charlie</div>
(2)v-for的key的解释
语法:key属性 = "唯一标识"
作用:给列表项添加的唯一标识,便于Vue进行列表项的正确排序复用。vue中使用的是虚拟DOM,会和原生的DOM进行比较,然后进行数据的更新,提高数据的刷新速度(虚拟DOM用了diff算法)。[想深入了解的可以点击参考此文](vue 虚拟 DOM_vdom树-CSDN博客)
如果你不给 v-for
渲染的每个项添加 key
,Vue 会发出警告,但并不会导致程序崩溃。没有为 v-for
添加 key
会导致 Vue 难以跟踪每个项的变化,可能会影响列表的性能和导致一些意外行为,特别是在涉及列表项的更新、删除和重新排序时。
注意点:
- key的值只能是字符串或者数字类型
- key的值必须具有唯一性
- 推荐使用id作为key(唯一),不推荐使用index作为key(会变化,不对应)
(3)v-for可以循环的变量
在 Vue.js 中,v-for
指令可以用于循环遍历多种数据类型,包括:
-
数组:你可以直接在
v-for
中使用数组,循环渲染数组中的每一项。<ul> <li v-for="item in names" :key="item.id">{{ item.name }}</li> </ul> data: { names: ['张三', '彭于晏', 'quan', 'xiao'], }, -
对象:你也可以在
v-for
中使用对象,循环渲染对象的属性值。<ul> <li v-for="(value, key) in object" :key="key">{{ key }}: {{ value }}</li> </ul> data: { userinfo: {name: 'xiao', age: 18, hobby: 'play'}, }, -
数字:你可以使用整数来指定循环的次数。
<ul> <li v-for="n in 10" :key="n">{{ n }}</li> </ul> -
字符串:你可以在
v-for
中使用 字符串。<ul> <li v-for="value in s" :key="value">{{value}}</li> </ul> data: { s: 'xiao is very handsome' },
6、数据双向绑定
(1)v-model
作用:针对 input 标签,在页面中输入值,js中有对应变量,双向数据绑定,可以快速获取或设置表单元素内容
语法:v-model="变量"
- 数据单向绑定:变量变了页面也会变;但是页面变,变量不会变
- 数据双向绑定:变量变化,页面会自动更新;视图变化,数据也会自动更新
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./vue/vue.js"></script> </head> <body> <div id="app"> <h1>数据单向绑定</h1> <input type="text" :value="name"> <h1>数据双向绑定</h1> <input type="text" v-model="name2"> </div> </body> <script> var vm = new Vue({ el: '#app', data: { name: 'xiao', name2:'sss' } }) </script> </html>
(2)v-model 应用于其他表单元素
在 Vue.js 中,v-model
指令通常用于在表单元素上创建双向数据绑定。这意味着当表单元素的值发生变化时,与之关联的 Vue 实例的数据也会相应地更新,反之亦然。虽然 v-model
最常用于 <input>
元素,但它也可以应用于其他表单元素,如 <select>
和 <textarea>
。
例如,你可以在 <select>
元素上使用 v-model
来创建双向数据绑定,示例如下:
<select v-model="selectedOption"> <option value="option1">Option 1</option> <option value="option2">Option 2</option> <option value="option3">Option 3</option> </select>
在上面的示例中,selectedOption
是 Vue 实例中的一个数据属性,它将与 <select>
元素的选定选项进行双向绑定。当用户选择不同的选项时,selectedOption
的值将更新,反之亦然。
同样地,你也可以在 <textarea>
元素上使用 v-model
来实现双向数据绑定,例如:
<textarea v-model="message" placeholder="Enter your message"></textarea>
在这个示例中,message
是 Vue 实例中的一个数据属性,它将与 <textarea>
元素的内容进行双向绑定。当用户在文本区域中输入内容时,message
的值将相应地更新,反之亦然。
总之,v-model
可以应用于不同类型的表单元素,以实现双向数据绑定,使得数据的更新能够与用户界面的交互实时同步。
三、事件处理
1、input 标签的事件处理
事件 | 说明 |
---|---|
input | 当输入框进行输入的时候 触发的事件 |
change | 当元素的值发生改变时 触发的事件 |
blur | 当输入框失去焦点的时候 触发的事件 |
focus | 当输入框获取焦点的时候 触发的事件 |
change
和blur
最本质的区别:
- 如果输入框为空,失去焦点后,change不会触发,但是blur会触发
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./vue/vue.js"></script> </head> <body> <div id="app"> <h1>input事件</h1> <input type="text" v-model="name1" @input="handleInput">-->{{name1}} <h1>change事件</h1> <input type="text" v-model="name2" @change="handleChange">-->{{name2}} <h1>blur事件</h1> <input type="text" v-model="name3" @blur="handleBlur">-->{{name3}} <h1>focus事件</h1> <input type="text" v-model="name4" @focus="handleFocus">-->{{name4}} </div> </body> <script> var vm = new Vue({ el: '#app', data: { name1:'', name2:'', name3:'', name4:'asdfasd', }, methods:{ handleInput(event){ console.log(event.data) }, handleChange(){ console.log('handleChange') }, handleBlur(){ console.log('handleBlur') }, handleFocus(){ console.log('Focus') this.name4='' } } }) </script> </html>
2、过滤案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./Vue/vue.js"></script> </head> <body> <div id="app"> <h2>过滤案例</h2> <input type="text" v-model="search" @input="handleSearch"> <ul> <li v-for="item in newDataList">{{item}}</li> </ul> </div> </body> <script> var vm = new Vue({ el: '#app', data: { search: '', dataList: ['a', 'ac', 'bdsfc', 'ffaw', 'casdad', 'atnefk', 'fwead', 'fewfe'], newDataList: ['a', 'ac', 'bdsfc', 'ffaw', 'casdad', 'atnefk', 'fwead', 'fewfe'] }, methods: { // 1、笨办法 handleSearch(event) { console.log(this) // 这个this是vue实例 var _this = this // 过滤dataList中每一个是否包含用户输入的 this.search this.newDataList = this.dataList.filter(function (item) { console.log(_this) // this是window的对象,要换成_this return item.indexOf(_this.search) >= 0 }) }, // // 2、箭头函数的写法 把function去掉,在形参括号和函数体大括号之间加个 => // handleSearch(event) { // this.newDataList = this.dataList.filter(item => item.indexOf(this.search) >= 0) // }, } }) </script> </html>
在我们构造逻辑时存在两个问题
- 函数里面的this指向的是window对象---> 在外部定义一个_this=this就可以了
- 改数据是在dataList上改的,回退搜索的关键字时就无法显示了---> 再写一个newDataList,在这上操作就可以了
3、补充 数组的过滤和判断子字符串是否在字符串中
// 补充1 数组的过滤 var dataList = ['a', 'ac', 'bdsfc', 'ffaw', 'casdad', 'atnefk', 'fwead', 'fewfe'] // 1、过滤掉所有 var newDataList = dataList.filter(function (item){ return true // 2、只保留长度大于2的 var newDataList = dataList.filter(function (item){ if (item.length > 2){ return true }else{ return false } }) console.log(newDataList) // 3、只保留包含at的 var search = 'at' var newDataList = dataList.filter(function (item){ return item.indexOf(search) >= 0 }) console.log(newDataList) // 补充2 判断子字符串是否在字符串中 var search = 'at' var s = 'attr' var res = s.indexOf(search) // 字符串在字符串的哪个位置 console.log(res)
四、箭头函数
箭头函数(Arrow Functions)是 ES6(ECMAScript 2015)引入的一种新的函数定义方式,它提供了一种更简洁的语法来定义函数。与传统的函数定义方式相比,箭头函数具有以下特点和优势:
-
简洁的语法:箭头函数可以让你用更短的代码来定义函数,尤其适合于简单的函数表达式。
-
更简洁的语法:当函数只有一个参数时,你可以省略参数周围的括号。当函数体只有一条语句时,你可以省略花括号和
return
关键字。 -
绑定
this
:箭头函数的this
值在函数创建时就已经确定,并且在整个函数生命周期内保持不变,它不会被函数的调用方式所影响。这解决了传统函数中this
值难以理解和控制的问题,特别适合于在回调函数中使用。 -
不绑定
arguments
对象:箭头函数不绑定arguments
对象,而是继承父级函数的arguments
对象。如果你需要访问函数的参数,可以使用 rest 参数或者通过...args
来获取所有参数。 -
不能作为构造函数:箭头函数不能用作构造函数,也就是不能通过
new
关键字来调用,因为它没有自己的this
值。 -
没有
arguments
对象:箭头函数没有自己的arguments
对象,如果需要访问函数的参数,可以使用 rest 参数或者通过...args
来获取所有参数。
下面是一些箭头函数的示例:
// 正常的匿名函数 var f = function (name) { console.log(name) } f('xiao') // 箭头函数写法 把function去掉,在形参括号和函数体大括号之间加个 => // 1、无参数无返回值 var f = () => { console.log('fff') } f() // 2、有一个参数无返回值 var f = (name) =>{ console.log(name) } f('xiao') // 如果只有一个参数可以简写成 但是如果有多个那么就必须加在括号里 var f = name =>{ console.log(name) } f('xiao') // 3、有多个参数无返回值(箭头函数的返回值是对象时,需要用括号包裹) var f2 = (name,age) => { console.log(name,age) } f2() // 4、有一个参数有一个返回值 var f = name =>{ return name+'nb' } var res = f('xiao') console.log(res) // 如果没有其他代码可以简写成 var f = name => name + 'nnb' var res = f('xiao') console.log(res)
重点:箭头函数内部,没有自己this,箭头函数内部用this ==> 就是上一个作用域的this
五、指令的修饰符
1、事件修饰符
事件修饰符 | 释义 |
---|---|
.stop | 只处理自己的事件,父控件冒泡的事件不处理(阻止事件冒泡),写在子标签上 |
.self | 只处理自己的事件,子控件冒泡的事件不处理,写在父标签上 |
.prevent | 阻止a链接的跳转 |
.once | 事件只会触发一次(适用于抽奖页面) |
使用修饰符时,使用顺序很重要;相应的代码会以同样的顺序产生
- 用
v-on:click.prevent.self
会阻止所有的点击- 而
v-on:click.self.prevent
只会阻止对元素自身的点击
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./Vue/vue.js"></script> </head> <body> <div id="app"> <h1>事件修饰符</h1> <h2>.once:只能点击一次</h2> <button @click.once="handleClick">点我有惊喜</button> <h2>.prevent:阻止a的跳转</h2> <a href="https://www.baidu.com" @click.prevent="handleA">点我看美女</a> <h2>.stop:只处理自己的事件,父控件冒泡的事件不处理(阻止事件冒泡)</h2> <h3>写在子标签上</h3> <ul @click="handleUl"> <li @click.stop="handleLi">li01</li> <li>li02</li> </ul> <h2>.self:只处理自己的事件,子控件冒泡的事件不处理(阻止事件冒泡)</h2> <h3>写在父标签上</h3> <ul @click.self="handleUl"> <li @click="handleLi">li01</li> <li>li02</li> </ul> </div> </body> <script> var vm = new Vue({ el: '#app', data: {}, methods: { handleClick() { alert('我是弹窗') }, handleA() { console.log('点过了') location.href = 'https://www.cnblogs.com' }, handleUl() { console.log('我是ul') }, handleLi() { console.log('我是li') }, } }) </script> </html>
2、按键修饰符
按键修饰符是 Vue.js 中用于监听键盘事件的一种方式。它们可以让你在处理键盘事件时更加灵活和方便。是一些常用的按键修饰符及其作用:
-
.enter
:监听 Enter 键。 -
.tab
:监听 Tab 键。 -
.delete
或.backspace
:监听删除键。 -
.esc
:监听 Esc 键。 -
.space
:监听空格键。 -
.up
:监听上箭头键。 -
.down
:监听下箭头键。 -
.left
:监听左箭头键。 -
.right
:监听右箭头键。 -
.ctrl
:监听 Ctrl 键。 -
.alt
:监听 Alt 键。 -
.shift
:监听 Shift 键。
这些按键修饰符可以与事件监听指令(如 @keydown
、@keyup
、@keypress
)一起使用,以便在特定的键被按下时触发相应的事件处理函数。例如:
<input @keydown.enter="submitForm"> <input @keyup.tab="focusNextInput"> <input @keypress.space="playPauseVideo"> <input @keyup.13="focusNextInput"> # @keyup.Keycode也能实现
六、表单控制
1、checkbox选中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>checkbox</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="app"> <h3>用户登录示例</h3> <p>用户名:<input type="text" v-model="username"></p> <p>密码:<input type="password" v-model="pwd"></p> <p>是否记住密码:<input type="checkbox" v-model="rem"></p> </div> </body> <script> var vm = new Vue({ el: '#app', data: { username: '', pwd: '', rem: '', // 只做选中或者不选中判断,使用布尔 }, }) </script> </html>
2、radio单选
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>单选</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="app"> <p>性别: <input type="radio" v-model="gender" value="男">男 <input type="radio" v-model="gender" value="女">女 <input type="radio" v-model="gender" value="保密">保密 </p> </div> </body> <script> var vm = new Vue({ el: '#app', data: { gender: '' }, }) </script> </html>
3、checkbox多选
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>多选</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="app"> <p>爱好: <input type="checkbox" v-model="hobbys" value="足球">足球 <input type="checkbox" v-model="hobbys" value="篮球">篮球 <input type="checkbox" v-model="hobbys" value="乒乓球">乒乓球 </p> </div> </body> <script> var vm = new Vue({ el: '#app', data: { hobbys: [], // 放多个元素需要使用数组 }, }) </script> </html>
4、购物车案例 - 结算
- 选中商品并自动计算总价 数量 * 价格
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./Vue/vue.js"></script> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js"></script> </head> <body> <div id="app"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1 class="text-center">购物车</h1> <table class="table table-bordered table-striped"> <thead> <tr> <th scope="col">商品id</th> <th scope="col">商品名字</th> <th scope="col">商品数量</th> <th scope="col">商品价格</th> <th scope="col">操作</th> </tr> </thead> <tbody> <tr v-for="good in goodsList"> <td>{{good.id}}</td> <td>{{good.name}}</td> <td>{{good.count}}</td> <td>{{good.price}}</td> <td><input type="checkbox" v-model="checkGoodList" :value="good"></td> </tr> </tbody> </table> <hr> <h3>选中的商品:{{checkGoodList}}</h3> <!-- 插值插入的方法的返回值--> <h3>总价格:{{getPrice()}}</h3> </div> </div> </div> </body> <script> var vm = new Vue({ el: '#app', data: { goodsList: [ {id: 1, name: '键盘', count: 2, price: 133}, {id: 2, name: '鼠标', count: 10, price: 12}, {id: 3, name: '背包', count: 34, price: 34}, {id: 4, name: '冲锋衣', count: 3, price: 67}, {id: 5, name: '显示器', count: 9, price: 89} ], checkGoodList: [] }, methods: { getPrice() { // 计算选中的总价格 var total = 0 // 循环选中的,计算总价格this.checkGoodList for (var item of this.checkGoodList) { console.log(item) total += item.price * item.count } return total } } }) </script> </html>
5、购物车案例 - 全选/全不选
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./Vue/vue.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js"></script> </head> <body> <div id="app"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1 class="text-center">购物车</h1> <table class="table table-bordered table-striped"> <thead> <tr> <th scope="col">商品id</th> <th scope="col">商品名字</th> <th scope="col">商品数量</th> <th scope="col">商品价格</th> <th scope="col">全选/全不选 <input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th> </tr> </thead> <tbody> <tr v-for="good in goodsList"> <td>{{good.id}}</td> <td>{{good.name}}</td> <td>{{good.count}}</td> <td>{{good.price}}</td> <td><input type="checkbox" v-model="checkGoodList" :value="good" @change="handleCheckOne"></td> </tr> </tbody> </table> <hr> <h3>选中的商品:{{checkGoodList}}</h3> <h3>是否全选:{{checkAll}}</h3> <!-- 插值插入的方法的返回值--> <h3>总价格:{{getPrice()}}</h3> </div> </div> </div> </body> <script> var vm = new Vue({ el: '#app', data: { goodsList: [ {id: 1, name: '键盘', count: 2, price: 133}, {id: 2, name: '鼠标', count: 10, price: 12}, {id: 3, name: '背包', count: 34, price: 34}, {id: 4, name: '冲锋衣', count: 3, price: 67}, {id: 5, name: '显示器', count: 9, price: 89} ], checkGoodList: [], checkAll: false, }, methods: { getPrice() { // 计算选中的总价格 var total = 0 // 循环选中的,计算总价格this.checkGoodList for (var item of this.checkGoodList) { console.log(item) total += item.price * item.count } return total }, handleCheckAll() { if (this.checkAll) { // 全选了 this.checkGoodList = this.goodsList } else { // 全不选 this.checkGoodList = [] } }, handleCheckOne() { // 如果checkGoodList等于商品总长度,说明权限了,让checkAll等于true if (this.checkGoodList.length == this.goodsList.length) { this.checkAll = true } else { // 只要长度不等,都是false this.checkAll = false } }, } }) </script> </html>
6、购物车案例 - 数量加减
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./Vue/vue.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js"></script> </head> <body> <div id="app"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1 class="text-center">购物车</h1> <table class="table table-bordered table-striped"> <thead> <tr> <th scope="col">商品id</th> <th scope="col">商品名字</th> <th scope="col">商品数量</th> <th scope="col">商品价格</th> <th scope="col">全选/全不选 <input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th> </tr> </thead> <tbody> <tr v-for="good in goodsList"> <td>{{good.id}}</td> <td>{{good.name}}</td> <td><span class="btn" @click="handleAdd(good)">+</span> <input type="text" v-model="good.count"> <span class="btn" @click="handleMin(good)">-</span></td> <td>{{good.price}}</td> <td><input type="checkbox" v-model="checkGoodList" :value="good" @change="handleCheckOne"></td> </tr> </tbody> </table> <hr> <h3>选中的商品:{{checkGoodList}}</h3> <h3>是否全选:{{checkAll}}</h3> <!-- 插值插入的方法的返回值--> <h3>总价格:{{getPrice()}}</h3> </div> </div> </div> </body> <script> var vm = new Vue({ el: '#app', data: { goodsList: [ {id: 1, name: '键盘', count: 2, price: 133}, {id: 2, name: '鼠标', count: 10, price: 12}, {id: 3, name: '背包', count: 34, price: 34}, {id: 4, name: '冲锋衣', count: 3, price: 67}, {id: 5, name: '显示器', count: 9, price: 89} ], checkGoodList: [], checkAll: false, }, methods: { getPrice() { // 计算选中的总价格 var total = 0 // 循环选中的,计算总价格this.checkGoodList for (var item of this.checkGoodList) { console.log(item) total += item.price * item.count } return total }, handleCheckAll() { if (this.checkAll) { // 全选了 this.checkGoodList = this.goodsList } else { // 全不选 this.checkGoodList = [] } }, handleCheckOne() { // 如果checkGoodList等于商品总长度,说明权限了,让checkAll等于true if (this.checkGoodList.length == this.goodsList.length) { this.checkAll = true } else { // 只要长度不等,都是false this.checkAll = false } }, handleAdd(good) { // 传的是对象 不是数字或者id good.count++ }, handleMin(good) { if (good.count > 1) { good.count-- } else { alert('不能再减了') } }, } }) </script> </html>
七、v-model进阶用法
属性 | 说明 |
---|---|
lazy | 等待input框的数据绑定失去焦点之后再变化 |
number | 数字开头,只保留数字,后面的字母不保留;字母开头,都保留 |
trim | 去除首尾的空格 |
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>v-model 之 lazy、number、trim</title> <script src="./Vue/vue.js"></script> </head> <body> <div id="box"> <input type="text" v-model="myText1" placeholder="normal"> {{myText1}} <br> <input type="text" v-model.lazy="myText2" placeholder="lazy"> {{myText2}} <br> <input type="text" v-model.number="myText3" placeholder="number"> {{myText3}} <br> <input type="text" v-model.trim="myText4" placeholder="trim"> {{myText4}} </div> </body> <script> var vm = new Vue({ el: '#box', data: { myText1: '', myText2: '', myText3: '', myText4: '', }, }) </script> </html>
八、前后端交互的三种方式
思维逻辑:前后端要打通----> 从前端发送ajax---> 核心:使用js发送http请求,接收返回
1、使用 jQuery 的 Ajax 方法
- jQuery 提供了方便的
$.ajax()
方法,封装了原生的 XMLHttpRequest 对象,简化了开发者的操作流程。 - 它支持跨浏览器兼容性,并提供了丰富的功能选项,如设置请求类型、请求头、处理错误等。
- 然而,由于现代前端框架(如 Vue.js)一般不推荐使用 jQuery,因此在与这些框架结合使用时可能不太适合。
后端
# # flask框架构建后端入口 from flask import Flask, jsonify app = Flask(__name__) @app.route('/userinfo', methods=['GET']) def userinfo(): res = jsonify({'username': 'xiao', 'age': 13}) res.headers = {'Access-Control-Allow-Origin':'*'} return res if __name__ == '__main__': app.run()
前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./Vue/vue.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js"></script> </head> <body> <div id="app"> <h1>与后端交互</h1> <button @click="handleLoad">加载用户信息</button> <p>用户名:{{username}}</p> <p>年龄:{{age}}</p> </div> </body> <script> var vm = new Vue({ el: '#app', data: { username: '', age: '', }, methods: { handleLoad() { // 后端发送请求,拿到数据,赋值给username和age 页面就有了 // 1.发送请求方式1:使用jq的ajax $.ajax({ url: 'http://127.0.0.1:5000/userinfo', method: 'get', success: data => { // 会导致CORS policy 跨域问题---> 解决方案:在后端响应头里加入:Access-Control-Allow-Origin即可 // console.log(data) data = JSON.stringify(data) this.username = data.username this.age = data.age } }) } } }) </script> </html>
2、使用原生js的fetch发送ajax请求
- 这是一种传统的方式,通过使用 JavaScript 的 XMLHttpRequest 对象来发送和接收数据。
- 开发者需要手动处理请求和响应的各个阶段,包括请求参数的拼装、请求头的设置、监听响应事件等。
- 尽管这种方法具有灵活性,但是编写和维护复杂度较高,需要考虑不同浏览器的兼容性问题。
<script> var vm = new Vue({ el: '#app', data: { username: '', age: '', }, methods: { handleLoad() { // 后端发送请求,拿到数据,赋值给username和age 页面就有了 // 1.发送请求方式2:使用原生js的fetch发送ajax请求 fetch('http://127.0.0.1:5000/userinfo').then(response => { return response.json(); }).then(data => { this.username = data.username this.age = data.age }); } } }) </script>
3、使用第三方库(如 Axios 或 Fetch)
- 第三方库如 Axios 和 Fetch 提供更简洁、易用且功能强大的方式来发送 Ajax 请求。它们以 Promise 或 async/await 为基础,使得异步请求代码更加清晰和易于维护。
- Axios 是一个流行的第三方库,广泛应用于前端项目中。同时,原生的 Fetch API 也是一种现代的标准方式,但需要注意兼容性问题
- axios官网:http://www.axios-js.com/
<script> var vm = new Vue({ el: '#app', data: { username: '', age: '', }, methods: { handleLoad() { // 后端发送请求,拿到数据,赋值给username和age 页面就有了 // 1.发送请求方式3:使用axios发送请求 axios.get('http://127.0.0.1:5000/userinfo') .then(res => { console.log(res.data) //真正的响应体数据是在res.data中 this.username = res.data.username this.age = res.data.age }) .catch(error => { console.log(error) }); } } }) </script>
九、补充
1、JS中的for循环操作
(1)基于索引的循环--> 最基本的
for (var i = 0; i < 10; i++){ console.log(i) }
(2)in 循环
var names = ['xiao','quan','zha'] // 数组 for (items in names) // 循环索引 console.log(items) console.log(names[items]) } var userinfo = {'name':'xiao','age':13} // 对象 for (items in userinfo){ // 循环的是key console.log(userinfo[items]) } var s = 'xiao' // 字符串 for(items in s){ // 循环的是索引 console.log(s[items]) }
(3)of循环
var names = ['xiao','quan','zha'] // 数组 for (items of names) // 循环 具体值 console.log(items) } var s = 'xiao' // 字符串 for (items of s) { // 循环具体值 console.log(items) } var userinfo = {'name':'xiao','age':13} // of不能循环对象 for (items of userinfo){ console.log(items) } for (items of 10) { // of不能循环数字 console.log(items) }
(4)数组的forEach方法,实现循环
var names = ['xiao','quan','zha'] names.forEach(function (value,index){ console.log(index) console.log(value) })
(5)jquery的each循环
var names = ['xiao','quan','zha'] // 数组 $.each(names,function (value,index){ console.log(value) console.log(index) }) var userinfo = {'name':'xiao','age':13} // 对象 $.each(userinfo,function (key,value){ console.log(key) console.log(value) }) var s = 'xiao' // 字符串不行 $.each(s,function (index,value){ console.log(index) console.log(value) })
2、vm对象介绍
<body> <div id="app"> <!--插值语法--> <h1>{{name}}</h1> <br> <h2> 方法中的 this 对象 </h2> <button @click="handleClick1">点我</button> </div> </body> <script> <!-- 将创建的Vue对象封装到 vm 变量里面。控制台全局可以通过 vm.name 取值 --> // 写在 data 或 methods 中的属性或方法,可以从 vm 中直接 通过 vm.属性取值 // methods的函数中,如果想使用data或methods中的属性,直接this.名字 就可以了 var vm = new Vue({ el: "#app", data: { name: "dream", }, methods: { handleClick1() { console.log(this) // this 就是当前的 实例的 vm 对象 // xr {_uid: 0, _isVue: true, __v_skip: true, _scope: t, $options: {…}, …} } }, }) </script>
vm
是一个Vue实例对象的变量名。
- Vue实例对象是Vue.js框架中最核心的概念之一,它扮演着连接数据和视图的桥梁作用。
- 数据绑定:
- 通过将
vm
对象传递给模板语法,可以实现数据的动态渲染。- 例如,在模板中使用
{{name}}
的插值语法,name
会被vm
对象中的data
属性中的name
所替换,从而实现了name
数据的动态展示。- 方法调用:
- 在
vm
对象的methods
属性中定义的方法,可以通过模板中的事件绑定(如@click="handleClick1"
)来进行调用。- 在这个例子中,当点击按钮时,会触发
handleClick1
方法,输出this
对象。- 在方法中,
this
指向当前的Vue实例对象vm
,通过this
可以访问到vm
实例中的属性和方法。- 总结起来,
vm
对象是Vue实例对象的引用,通过这个对象可以访问和操作Vue实例的数据和方法。
- 它的作用是管理数据和行为,实现数据的双向绑定,以及处理用户交互和响应。
- 在模板中可以通过
vm
对象来访问数据,并触发相应的方法来实现业务逻辑的处理。
十、 小练习
- 要求:点击按钮,加载最新电影
- 前端:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./vue/vue.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> </head> <body> <div id="app"> <h1>点击按钮,获取数据,显示</h1> <button @click="handleLoad">获取电影信息</button> <div v-for="item in filmList"> <p>电影名:{{item.name}}</p> <p>介绍:{{item.synopsis}}</p> <p>图片: <img :src="item.poster" alt="" height="300px" width="150px"></p> <hr> </div> </div> </body> <script> var vm = new Vue({ el: '#app', data: { filmList: [], }, methods: { handleLoad() { axios.get('http://127.0.0.1:5000/films') .then(res => { this.filmList=res.data.result }) .catch(error => { console.log(error); }); } } }) </script> </html>
- 后端:
# pip install flask from flask import Flask, jsonify import json app = Flask(__name__) @app.route('/films') def films(): with open('./fiml.json', 'r', encoding='utf-8') as f: res_dict = json.load(f) res = jsonify(res_dict) res.headers['Access-Control-Allow-Origin'] = '*' return res if __name__ == '__main__': app.run()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构