VUE的事件绑定修饰符练习及vue列表渲染及条件渲染练习,vue键盘事件+数组方式参数的传递学习及vue的计算属性访问器属性及侦听属性练习以及vue注册组件自定义标签及子组件向父组件传参及父组件向父组
vue中事件绑定在vue中事件绑定时,es6中原生写法event在vue中需要增加$符号,使用$event在vue事件中,阻止默认点击或提交的默认事件使用.prevent,在vue中的阻止冒泡是使用.stop来操作,vue中的点击事件需放置到methods方法对象中vue绑定事件中常用代码及案例代码如下:
| vue中代码 | es6中代码 | 说明 |
|---|---|---|
| v-on:click/简写@ | 点击,回车等事件时,一般都是原生是以on开头,onclick | 在vue中使用指令v-on简写@ |
| $evnet | event | 在vue中与原生es6不同,增加了一个修身符号$ |
| .prevent | .preventDefault() | 阻止默认点击事件,在vue中更简单,使用.prevent |
| .stop | .defaultPrevented() | 在vue中阻止冒泡直接使用.stop |
| 新增方法对象methods:用于点击事件自定义事件值的函数放置在内中 |
代码部分:
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>事件绑定</title><script src="https://unpkg.com/vue@next"></script></head><body><!-- es6事件绑定写法 --><p><a href="http://www.php.cn" onclick="geturl()">es6事件绑定写法</a><span class="url"></span></p><script>function geturl(ele) {///阻止默认点击事件event.preventDefault();// 获取当前点击事件的标签主体const link = event.currentTarget;const link2 = event.target;console.log(link);console.log(link2);// 标签主体的下一个兄弟的,文本= link的urllink2.nextElementSibling.textContent = link2.href;}</script><!-- vue3的写法 事件绑定 --><div class="app"><p><!-- v-on是一个点击事件指令 简写符号为@ --><!-- es6中原生的evnet 但是在vue中是$evnet --><a href="http://php.cn" v-on:click="showurl($event)">vue3中实现双向绑定事件</a><span class="url">{{url}}</span></p><!-- ///////事件修饰符///////////// --><!-- 通过修饰符来禁止默认事件 使用 .prevent --><p><!-- 这里其实很好理解,this就是实例app中,url呢就是app中的url --><a href="http://php.cn" @click.prevent="this.url = $event.target ">VUE3中 事件修饰符的阻止默认事件实现</a><span class="url">{{url}}</span><!-- ////////////vue中的事件冒泡行为///////// --></p><p onclick=" alert('写作业中') "><!-- 这里其实很好理解,this就是实例app中,url呢就是app中的url --><!-- 这里事件已经进行了冒泡 所以用什么行为阻止呢? 使用.stop --><a href="http://php.cn" @click.prevent.stop="this.url = $event.target ">VUE3中 事件修饰符的实现阻止事件冒泡</a><span class="url">{{url}}</span></p></div><script>const app = Vue.createApp({data() {return {url: null,};},// 在原生的es6中,我们的点击事件是对应function函数的,但是在vue中是使用methods的// 所以这里的点击事件要写到methods函数中 就是把functon写到这个函数中methods: {// {}是一个对象,所以可以放多个值// 把点击事件的showurl方法写到里面showurl(ev) {// 阻止默认事件ev.preventDefault();// 我们看到在vue3中点击事件中的$event就等于es6中的eventconsole.log(ev);console.log(ev === event); //测试一下,发现页面输出的是true// console.log(this);这里打印的发现,这个this是vue中的实例console.log(ev.target);// 一直好奇target跟currentTarget 哪儿会有区别 每次看到target就像反着用curr来测试// this.url = ev.target.href;this.url = ev.currentTarget.href;},},}).mount(".app");</script></body></html>
示例截图(没给画图):
列表渲染之 for of列表的渲染其实分为三部分:1.数组渲染2.对象渲染3.数组中对象的渲染以及for of中 尽量都加一个v-bind:key指令,为提高效率使用diff算法数组渲染的格式是for(值,索引) of 数组而对象的渲染和对象的渲染稍微有一点不同格式是:for(值,键,索引) of 对象数组中对象的渲染,其实和数组渲染类似for(值,索引) of 对象剩下的使用部分和es6中其实是类似的写法,具体请看下面的代码吧代码部分:
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>vue之列表渲染</title><script src="https://unpkg.com/vue@next"></script></head><body><div class="app"><ul><li>{{cities[0]}}</li><li>{{cities[1]}}</li><li>{{cities[2]}}</li><li>{{cities[3]}}</li></ul><!-- array:指令 v-for ,对应es6中原生的for of --><!-- 下面是改写的方法 --><ul><!-- 指令的写法 --><!-- 从实例中就可以看出,cities是一个数组,city是数组每个成员赋给city --><!-- 那遍历的li标签内就应该放置city --><!-- 而且v-for指令支持索引,索引跟数组的每个成员是一个组合 --><li v-for="city of cities">{{city}}</li><li>---------------</li></ul><!-- 为了提交效率,为了借助diff算法,使用v-for指令时,需加一个v-bind:key指令,也就是:key指令 --><li v-for="(city,index) of cities" :key="index">数组中索引是{{index}},值是{{city}}</li></ul><!-- ///////用v-for指令遍历obj对象////// --><ul><!-- prop->property 代表属性 也就是当前对象的键 --><!-- item代表的是值,index代表的是索引 --><li v-for="(item,prop,index) of user" :key="index" > 对象中的键为:{{prop}},值为:{{item}},既然对象也是一个数组,那么输出一下他的索引{{index}} </li></ul><!-- //////开发中用到比较多的对象数组//////// --><ul><!-- 遍历一个数组 数组里面都是对象 --><!-- 数组是没有键的 --><!-- 当前item等于数组的值,也就是对象 --><li v-for="(item,index) of users" :key="index" >{{item.name}}"他的邮箱是"{{item.email}}</li></ul></div></body><script>const app = Vue.createApp({data() {return {// 先创建一个数组 arraycities: ["济南", "青岛", "北京", "上海"],//object对象遍历user:{name:"老王",email:"123456@qq.com"},///声明一个数组对象 arr-objusers:[{name:"老王",email:"123456@qq.com"},{name:"老刘",email:"11211111@qq.com"},{name:"老炸",email:"22222222@qq.com"},],};},}).mount(".app");</script></html>
示例截图(家里电脑小,将就一下吧,改天赚钱买个大的学前后端,给点力啊):
条件渲染之v-if/多分支v-else-if条件渲染部分一般使用v-if及多条件判断v-else-if来判断,并且下面演示中,在v-text中使用了es6中的,条件判断(简写的语法)代码部分:
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>vue中的条件渲染</title><script src="https://unpkg.com/vue@next"></script><!-- vue三部曲,引入,建立挂载点,然后实例挂载,学习中,感觉卡卡卡出来这么多代码 好有成就感...... --></head><body><div class="app"><!-- v-if指令 单分支判断 --><!-- 在p标签增加一个v-if指令 --><p v-if="metrue">{{message}}</p><!-- 点击事件,这里=!metrue是取反结果的意思, --><!-- 其中v-text中语法与es6中一样,不过要注意"及' --><button @click="metrue=!metrue" v-text="metrue ? '行' : '不行' "></button><!-- /////////////多分支 if else if else else vue中的写法 --><p v-if="point>=500 && point < 1000">{{namevip[0]}}</p><p v-else-if="point>=1000 && point < 2000">{{namevip[1]}}</p><p v-else="point>=2000">{{namevip[2]}}</p></div></body><script>const app = Vue.createApp({data() {return {// 将在p标签显示的内容,赋值给一个变量message: "今晚可能写不完作业,明天再写,行不行?",// 创建一个是否显示的标志metrue: true,namevip: ["月会员", "季会员", "年会员"],point: 3000,};},}).mount(".app");</script></html>
示例截图:
vue事件之键盘事件+数组方式参数传递此部分使用了键盘事件,演示了当用户提交一个值的使用方式,以及用户添加多个值的添加方式,其中又重新使用了es6中的.unshift给数组内传递N+参数,以及使用了昨天的v-for of方式循环遍历输出到页面中代码部分:
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>键盘事件指令</title><script src="https://unpkg.com/vue@next"></script></head><body><div class="app"><input type="text" @keydown="submint($event)" /><ul><li>{{item}}</li></ul><hr></hr><input type="text" @keydown="submint2($event)" /><ul><!-- 昨天刚做了v-for 今天差点忘了,模模糊糊写出来,还错了 又改的 --><li v-for="(item2,index) of list" @key="index">{{item2}}</li></ul></div></body><script>const app = Vue.createApp({data() {return {item: "", //但个值不行,那么启动数组方式list: []};},methods: {submint(ev) {console.log(ev.key);// 如果ev.key = Enterif (ev.key === "Enter") {// 那么ev函数获取到当前标签的value字段赋值给this实例里面的itemthis.item = ev.currentTarget.value;}},// 数组模式submint2(ev) {if (ev.key === "Enter") {// 回顾es6知识,.unshift是向数组内添加一个或者多个元素,所以这里是传参,其中unshift()括号内就是要传的参数this.list.unshift(ev.currentTarget.value)// 传参完毕后给value框清空操作ev.currentTarget.value = null}}},}).mount(".app");</script>/////////////////下面的这个是老师使用修饰符语法糖写的,原理是一样,///////看看有啥区别?其实就是当我这个键按下的是Enter回车键时就调用这个方法<body><div class="app"><!-- <input type="text" @keydown="submit($event)" /> --><input type="text" @keydown.enter="submit($event)" /><ul><li v-for="(item,index) of list" :key="index">{{item}}</li></ul></div><script>Vue.createApp({data() {return {list: [],}},methods: {submit(ev) {// console.log(ev.key)// if (ev.key === 'Enter') {// this.list.unshift(ev.currentTarget.value)// ev.currentTarget.value = null// }this.list.unshift(ev.currentTarget.value)ev.currentTarget.value = null},},}).mount('.app')</script></body></html></html>
示例截图:
vue计算属性/访问器属性案例:购物车价格计算流程,先通过访问器属性computed:计算出价格总和,再通过这侦听器属性watch:来侦听当前的总价格变化,watch:侦听器内总价格的属性有2个值,一个是新值,一个是旧值,侦听这两个值,然后对新值进行折扣计算,折扣计算后watch里面的值的属性,最后都会归并到data实例中,通过实例打入app页面html中,在watch中进行价格计算computed:访问器属性来计算mon的值,最后会返回到data实例中示例区块代码:
//访问器计算属性 是: 不是()函数 找错误找了半天 靠computed: {mon: {get() {return this.price * this.num;},},},
watch:侦查器属性讲需要循环判断的代码放到侦查器属性中,类似下面的mon总和的值,来侦听总和的值区块示例代码:
// 侦听器属性 来通过值的变化来判断折扣结果watch: {//侦听当前总金额的变化// 侦听属性的变化有2个值,侦听的那个属性的当前的值,和原值/旧值// mon(当前的值/新值,原值/旧值)mon(mona, monb) {console.log(mona, monb); //在这里就是侦听购物车的当前价格 和原来的价格switch (true //循环判断开始) {case mona >= 500 && mona < 1000:// 折扣的价格 actualmon 就等于原价*折扣价格this.actualmon = this.mon * 0.9;break;default:// 无折扣情况下就默认价格this.actualmon = this.mon;break;}// 实际中折扣了多少钱 不就是原价-折扣后的价格?this.discountmon = this.mon - this.actualmon; //最后合并到data示例中},},
声明周期函数:mounted(){}
mounted() {this.num = 1; //这里要注意的是 num 的1 必须要比data中实例的1要大},
代码示例:
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><script src="https://unpkg.com/vue@next"></script><title>vue中的访问器属性计算属性侦听器属性</title></head><body><!-- <div class="app">{{a}}+{{b}}={{sum}}</div> --><div class="app"><table><caption>购物车</caption><thead><tr><th>ID</th><th>品名</th><th>单价</th><th>数量</th><th>金额</th></tr></thead><tbody><tr><td>HA110</td><td>蒙牛纯牛奶</td><td>{{price}}</td><!-- 使用:value属性是错误的,更新数量时,在页面中与实例中的num值始终绑定的,不会更新 --><!-- <td><input type="number" :value="num"></td> --><!-- 该怎么样绑定数量更新呢? 使用v-model 双向绑定--><td><input type="number" v-model="num" /></td><!-- <td>{{price*num}}</td>//数量等于50 --><!-- 下面使用计算属性进行计算金额的值 --><td>{{mon}}</td></tr></tbody></table><!-- <p>实付金额为:{{actualmon}},原价为:{{mon}},折扣了{{mon-actualmon}}</p> --><p>实付金额为:{{actualmon}},原价为:{{mon}},折扣了{{discountmon}}</p><!-- 通过在侦听器上增加一个属性,赋值给折扣价格discountmon --><!-- //{{discountmon}} --></div></body><!-- <script>const app = Vue.createApp({data() {return {a: 1,b: 2,};},// 计算属性//也就是es6中的访问器属性// vue中计算属性有个语法糖为 computedcomputed: {// 本身computed就是访问器属性 get sum:前面的get可以不要了,但不代表不写,需要写到里面sum: {get() {return this.a + this.b;},},},}).mount(".app");</script> --><script>const app = Vue.createApp({data() {return {price: 50,num: 0,};},//访问器计算属性 是: 不是()函数 找错误找了半天 靠computed: {mon: {get() {return this.price * this.num;},},},// 侦听器属性 来通过值的变化来判断折扣结果watch: {//侦听当前总金额的变化// 侦听属性的变化有2个值,侦听的那个属性的当前的值,和原值/旧值// mon(当前的值/新值,原值/旧值)mon(mona, monb) {console.log(mona, monb); //在这里就是侦听购物车的当前价格 和原来的价格switch (true //循环判断开始) {case mona >= 500 && mona < 1000:// 折扣的价格 actualmon 就等于原价*折扣价格this.actualmon = this.mon * 0.9;break;default:// 无折扣情况下就默认价格this.actualmon = this.mon;break;}// 实际中折扣了多少钱 不就是原价-折扣后的价格?this.discountmon = this.mon - this.actualmon; //最后合并到data示例中},},// 当开发完上面的之后,你发现保存后的价格并没有真实的改变,就是没初始化,需要初始化一下当前的价格mounted() {this.num = 1; //这里要注意的是 num 的1 必须要比data中实例的1要大},}).mount(".app");</script><style>table {width: 26em;text-align: center;border-collapse: collapse;}table caption {font-size: 1.5em;margin-bottom: 0.6em;}thead {background-color: lightcyan;}th,td {border: 1px solid #000;height: 2em;}</style></html>
代码已完成 来看看截图吧
vue注册组件之自定义标签说的可能不太明白,请看1月14日的视频注册组件需要用vue自带的属性app.component 来实现,且有两个值,一个值为注册标签的名字,第二个为,标签的行为,比如我注册一个标签名字为ButtonCounter,后面他的行为就是一个点击按钮,后面的行为需要放到{}中,并且行为要放到一个系统自带的template属性中,注册的标签需放到html中,因为html不区分大小写,所以标签的命名需改为蛇形命名,如:ButtonCounter,在html页面中需改为button-counter
第二种,与html结合放到页面中放到页面中,需要在页面放到<template id="counter"></template>标签中,然后再注册组件的内部,绑定template的id,然后将html再放到html中,请注意下面的代码部分属性代码:app.component注册组件/标签template模板参数ButtonCounter 自定义属性,遇大写蛇形命名传递到html页面props向html的template中传递ButtonCounter中的参数(向子组件传参)
///////////////////////////////////////声明多个组件,可以使用compoents,需在主组件下面声明//////////////////看看截图吧,没事需要看看手册
代码部分:
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><script src="https://unpkg.com/vue@next"></script><title>vue组件全局组件</title></head><body><div class="app"><div v-text="'hello'"></div><!-- vue自定义标签组件 --><!-- 自定义组件如果名称有大小写,需要将大小写改成小写且改成蛇形命名 --><button-counter></button-counter></div><!-- ///////////////////第二个自定义标签//////// --><template id="counter"><button @click="count++">点赞: {{count}}</button></template></body><script>const app = Vue.createApp({});//注册组件 创建组件,创建组件时,组件要放到app实例的外面// 组件的名称就是app.component('组件名称',{组件的行为});app.component("ButtonCounter", {// 使用template属性声明一下,注意template 是vue自带的属性,不可更改// template: '<button @click="count++" >点赞{{count}}</button>',// 将tmplate的值进行和html绑定,绑定到页面中,需使用template包裹,且定义一个id 如下定义了一个countertemplate: "#counter",data() {return {count: 0,};},});// 创建组件时,挂载要延时挂载,感觉意义上是,实例下面写自定义组件,到最后部分,才进行绑定到app示例中,然后渲染到html页面中app.mount(".app");</script></html>
示例截图:
注册组件之向子属性传参:上面说的是全局组件,下面是全局组件下子组件传参,通过向子组件template中传参,当自定义标签也就是父组件button-counter中有多个属性时,向子组件传参,通过props数组传递到html页面的template子组件中
代码部分:
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>vue子组件的传参</title><script src="https://unpkg.com/vue@next"></script></head><body><div class="app"><button-counter username="admin" email="123456@qq.com"></button-counter></div><template id="counter"><button @click="count++">点赞: {{count}}</button><p>{{username}}</p><p>{{email}}</p></template></body><script>// 1. 创建实例const app = Vue.createApp({});// 2. 注册组件app.component("ButtonCounter", {props: ["username", "email"],template: "#counter",data() {return {count: 0,};},});// 3. 绑定挂载点app.mount(".app");</script></html>
示例截图:
子组件向父组件传参 自己感觉流程就是,首先在子组件使用$emit()参数,在子组件html中定义一个自定义事件,然后再父组件进行监听,监听的参数就是子组件的自定义事件,值是自定义的一个事件方法事件的方法需要写在”创建的实例的data中“,因为@review-count是一个自定义事件,所以使用methods:{},把事件的值放到里面接收,当前的值就是review,当得到了值的结果时,然后进行处理,比如判断下面是老师的意思
- 向子组传传参: props: [….]
- 子组件向父组通信:2.1 子组件:
$emit(customEvent, ...args)2.2 父组件:@customEvent(...args)args可以是多个参数,可能是数组吧,这句话是我说的,不是老师一遍看不懂,就多看几遍吧代码部分:```php<!DOCTYPE html><html lang="zh-CN">
- 子组件向父组通信:2.1 子组件:
<head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>vue子组件的传参</title> <script src="https://unpkg.com/vue@next"></script></head>
<body> <div class="app"> <!-- 增加reviewCount增加监听自定义事件,调用一个方法,review自己写的,不是vue带的,来监听这个方法 --> <button-counter username="admin" email="123456@qq.com" @review-count="review"></button-counter> </div> <template id="counter"> <button @click="count++">点赞: {{count}}</button> <p>{{username}}</p> <p>{{email}}</p> <!-- 想拿到点赞数,就要搞清原理,点击触发是在button上触发,就像向父组件button-counter传递, --> <!-- 类似订阅事件,一对多触发,只要点击了事件就触发下面所有的功能走一遍 --> <!-- $emit()是一个方法,是一个发布,触发,发射的意思,支持两个参数,第一个是自定义事件,最终会被注册到发布订阅的调度中心,也是个数组,调度中心 --> <!-- 第二个是向父组件传递的参数 ,不一定有,需要就有,不需要就没有 --> <!-- $emit(自定义事件,向父组件传递的参数[可选]) 当写到这里的时候,需要在父组件,button-counter添加一个事件,来订阅接收,添加的自定义事件就是emint中的自定义事件,也就是监听自定义事件--> <button @click="$emit('reviewCount',this.count)">评价</button> </template></body>
<script> // 1. 创建实例 const app = Vue.createApp({ methods: { review(count) { console.log(count); if (count >= 5) { alert(“太牛了”); } }, }, });
// 2. 注册组件app.component("ButtonCounter", {props: ["username", "email"],template: "#counter",data() {return {count: 0,};},});// 3. 绑定挂载点app.mount(".app");
</script><!-- 自己感觉流程就是,首先在子组件使用$emit()参数,在子组件html中定义一个自定义事件,然后再父组件进行监听,监听的参数就是子组件的自定义事件,值是自定义的一个事件方法 --><!-- 事件的方法需要写在”创建的实例的data中“,因为@review-count是一个自定义事件,所以使用methods:{},把事件的值放到里面接收,当前的值就是review,当得到了值的结果时,然后进行处理,比如判断 --><!-- 下面是老师的意思 --><!-- // 1. 向子组传传参: props: [....] --><!-- // 2. 子组件向父组通信: --><!-- // 2.1 子组件: $emit(customEvent, ...args) --><!-- // 2.2 父组件: @customEvent(...args) --><!-- args可以是多个参数,可能是数组吧,这句话是我说的,不是老师 -->
</html>```示例截图: