VUE 添加事件、渲染、组件
程序员文章站
2022-04-17 18:46:39
...
<!-- 1. 实例演示为元素添加事件的正确方式 2. 实例演示条件渲染与列表渲染,特别是数组对象 3. 实例演示计算属性与侦听器, 并分析二者区别 4. 实例演示组件与组件之间的通信,特别是如何监听子组件的数据变化 -->
VUE 元素添加事件
- v-on: 事件指令 , 简写: @
- event, 在 vue3: $evnet
- 事件修饰符: 对当前的事件行为进行干预
- @click.prevent: 阻止默认行为
- @click.prevent.stop
<!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>
<!-- vue3 -->
<div class="app">
<p>
<!-- v-on: 事件指令 , @ -->
<!-- event, 在vue3: $evnet -->
<a href="helo10086.cn" v-on:click="showUrl($event)">vue1: 显示网址: </a>
<span class="url">{{url}}</span>
</p>
<!-- 事件修饰符: 对当前的事件行为进行干预 -->
<p>
<!-- v-on: 事件指令 , @ -->
<!-- event, 在vue3: $evnet -->
<!-- @click.prevent: 阻止默认行为 -->
<a href="helo10086.cn" @click.prevent="this.url = $event.target.href"
>vue2: 显示网址:
</a>
<span class="url">{{url}}</span>
</p>
<!-- 在父级上的同名事件,因为事件冒泡机制而被自动的调用了 -->
<p onclick="alert('hello help!')">
<!-- @click.stop: 阻止冒泡 -->
<a
href="helo10086.cn"
@click.prevent.stop="this.url = $event.target.href"
>vue3: 显示网址:
</a>
<span class="url">{{url}}</span>
</p>
</div>
<script>
const app = Vue.createApp({
data() {
return {
url: null,
};
},
methods: {
showUrl(ev) {
// 防止默认行为
ev.preventDefault();
console.log(ev === event);
// this -> vue实例
console.log(this);
console.log(ev.target);
this.url = ev.target.href;
},
},
}).mount(".app");
</script>
</body>
</html>
[http://help10086.cn/0114/demo1.html]
VUE 条件渲染与列表渲染
- v-for , 对应原生的 for - of
<!-- 列表渲染 -->
<!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>
<div class="app">
<!-- array: v-for , 对应原生的 for - of -->
<ul>
<!-- 提高效率,一定要加 :key 为了借助diff算法,key必须选择一个永远唯一的值 -->
<li v-for="(city,index) of cities" :key="index">{{index}}->{{city}}</li>
</ul>
<!-- obj: v-for -->
<ul>
<!-- prop -> property 属性 -->
<li v-for="(item,prop,index) of user" :key="index">
{{index}} ->{{prop}} => {{item}}
</li>
</ul>
<!-- ArrayObj: v-for -->
<ul>
<li v-for="(user,index) of users" :key="index">
{{user.name}}: ({{user.email}})
</li>
</ul>
</div>
<script>
const app = Vue.createApp({
data() {
return {
// array
cities: ["tayninh", "nhontrach", "longthanh"],
// object
user: {
name: "help",
email: "help@foxmail.com",
},
// array of object
users: [
{
name: "lan",
email: "lan@foxmail.com",
},
{
name: "hoang",
email: "hoang@foxmail.com",
},
{
name: "hope",
email: "hope@foxmail.com",
},
],
};
},
}).mount(".app");
</script>
</body>
</html>
<!-- 条件渲染 -->
<!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>
<div class="app">
<!-- if -->
<p v-if="flag">{{message}}</p>
<button @click="flag=!flag" v-text="flag ? '隐藏' : '显示'"></button>
<!-- if -- if else -- if else -- else -->
<p v-if="salary > 0 && salary < 2000">{{grade[1]}}</p>
<p v-else-if="salary >= 2000 && salary < 6000">{{grade[2]}}</p>
<p v-else-if="salary >= 6000 && salary < 10000">{{grade[3]}}</p>
<p v-else-if="salary >= 10000 && salary < 15000">{{grade[4]}}</p>
<p v-else-if="salary >= 15000">{{grade[5]}}</p>
<p v-else>{{grade[0]}}</p>
</div>
<script>
const app = Vue.createApp({
data() {
return {
message: "20220116, 准备领完年终奖,回家过年吧!",
flag: false,
// 会员级别
grade: [
"操作工",
"业务员",
"主管",
"一般管理",
"中层管理",
"高层管理",
],
// 积分
salary: 100000,
};
},
}).mount(".app");
</script>
</body>
</html>
列表渲染:[http://help10086.cn/0114/demo2.html]
条件渲染:[http://help10086.cn/0114/demo3.html]
VUE 计算属性与侦听器
- 例生命周期, mounted: 当 vue 实例加载完成的时候会自动调用(onload)
<!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" />
<script src="https://unpkg.com/vue@next"></script>
<title>计算属性,侦听器属性</title>
<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>
</head>
<body>
<div class="app">
<table>
<caption>
购物车
</caption>
<thead>
<tr>
<th>ID</th>
<th>品名</th>
<th>单价</th>
<th>数量</th>
<th>金额</th>
</tr>
</thead>
<tbody>
<tr>
<td>20220116</td>
<td>iphone 13</td>
<td>{{price}}</td>
<td><input type="number" v-model="num" style="width: 4em" /></td>
<!-- <td>{{price * num}}</td> -->
<td>{{payAmount}}</td>
</tr>
</tbody>
</table>
<!-- 侦听器来监听金额的变化,设置优惠价格:用户实际支付的钱 -->
<!-- <p>实付金额: {{disAmount}}, 优惠了 : <span style="color: red">{{payAmount-disAmount}}</span></p> -->
<p>
实付金额: {{disAmount}}, 优惠了 :
<span style="color: #ff0000">{{difAmount}}</span>
</p>
</div>
<script>
const app = Vue.createApp({
data() {
return {
price: 10000,
num: 0,
};
},
// 计算属性: 访问器属性
computed: {
payAmount: {
get() {
return this.price * this.num;
},
set(value) {
// 这个通常用来做测试
},
},
},
// 侦听器属性
watch: {
// current: 新值/当前值, origin: 原值/旧值
payAmount(current, origin) {
console.log(current, origin);
switch (true) {
case current > 10000 && current < 20000:
this.disAmount = this.payAmount * 0.99;
break;
case current >= 20000 && current < 30000:
this.disAmount = this.payAmount * 0.98;
break;
case current >= 30000 && current < 40000:
this.disAmount = this.payAmount * 0.97;
case current >= 40000 && current < 50000:
this.disAmount = this.payAmount * 0.96;
break;
case current > 50000:
this.disAmount = this.payAmount * 0.95;
break;
default:
this.disAmount = this.payAmount;
}
this.difAmount = this.payAmount - this.disAmount;
},
},
// 实例生命周期, mounted: 当vue实例加载完成的时候会自动调用(onload)
mounted() {
this.num = 1;
},
}).mount(".app");
</script>
</body>
</html>
[http://help10086.cn/0114/demo5.html]
VUE 组件与组件之间的通信
- 组件,vue 指令本质是自定义属性
- vue 组件本质就是自定义标签
- 子组件传参:自定义属性
- 监听子组件: $emit(自定义事件, 向父组件传递的参数[可选])
<!-- VUE组件 -->
<!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>
<div class="app">
<!-- vue指令 -> 自定义属性 -->
<div v-text="'hello'"></div>
<!-- vue组件 -> 自定义标签 -->
<button-counter></button-counter>
</div>
<template id="counter">
<button @click="count++">点赞: {{count}}</button>
</template>
<script>
// 1. 创建实例
const app = Vue.createApp({});
// 2. 注册组件
app.component("ButtonCounter", {
template: "#counter",
data() {
return {
count: 0,
};
},
});
// 3. 绑定挂载点
app.mount(".app");
</script>
</body>
</html>
<!-- 子组件传参 -->
<!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>
<div class="app">
<button-counter username="admin" email="admin@qq.com"></button-counter>
</div>
<template id="counter">
<button @click="count++">点赞: {{count}}</button>
<p>用户: {{username}}</p>
<p>邮箱: {{email}}</p>
</template>
<script>
// 1. 创建实例
const app = Vue.createApp({});
// 2. 注册组件
app.component("ButtonCounter", {
// 自定义属性
props: ["username", "email"],
template: "#counter",
data() {
return {
count: 0,
};
},
});
// 3. 绑定挂载点
app.mount(".app");
</script>
</body>
</html>
<!-- 监听子组件事件 -->
<!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>
<div class="app">
<button-counter
username="help"
email="help10086@foxmail.com"
@review-count="review"
></button-counter>
</div>
<template id="counter">
<button @click="count++">点赞: {{count}}</button>
<p>用户: {{username}}</p>
<p>邮箱: {{email}}</p>
<!-- 发布订阅 -->
<!-- $emit(自定义事件, 向父组件传递的参数[可选]) -->
<button @click="$emit('reviewCount', this.count)">评价</button>
</template>
<script>
// 1. 创建实例
const app = Vue.createApp({
methods: {
review(count) {
console.log(count);
if (count >= 20) {
alert("感谢家人的支持!");
}
},
},
});
// 2. 注册组件
app.component("ButtonCounter", {
props: ["username", "email"],
template: "#counter",
data() {
return {
count: 0,
};
},
});
// 3. 绑定挂载点
app.mount(".app");
// 1. 向子组传传参: props: [....]
// 2. 子组件向父组通信:
// 2.1 子组件: $emit(customEvent, ...args)
// 2.2 父组件: @customEvent(...args)
</script>
</body>
</html>
[http://help10086.cn/0114/demo7.html]
[http://help10086.cn/0114/demo8.html]