PHP8.1.21版本已发布
vue8.1.21版本已发布
jquery8.1.21版本已发布

博客列表 > VUE 添加事件、渲染、组件

VUE 添加事件、渲染、组件

赵大叔
赵大叔 原创
2022年01月16日 23:37:26 1078浏览

<!-- 1. 实例演示为元素添加事件的正确方式 2. 实例演示条件渲染与列表渲染,特别是数组对象 3. 实例演示计算属性与侦听器, 并分析二者区别 4. 实例演示组件与组件之间的通信,特别是如何监听子组件的数据变化 -->

VUE 元素添加事件

  • v-on: 事件指令 , 简写: @
  • event, 在 vue3: $evnet
  • 事件修饰符: 对当前的事件行为进行干预
  • @click.prevent: 阻止默认行为
  • @click.prevent.stop
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>事件绑定</title>
  8. <script src="https://unpkg.com/vue@next"></script>
  9. </head>
  10. <body>
  11. <!-- vue3 -->
  12. <div class="app">
  13. <p>
  14. <!-- v-on: 事件指令 , @ -->
  15. <!-- event, 在vue3: $evnet -->
  16. <a href="helo10086.cn" v-on:click="showUrl($event)">vue1: 显示网址: </a>
  17. <span class="url">{{url}}</span>
  18. </p>
  19. <!-- 事件修饰符: 对当前的事件行为进行干预 -->
  20. <p>
  21. <!-- v-on: 事件指令 , @ -->
  22. <!-- event, 在vue3: $evnet -->
  23. <!-- @click.prevent: 阻止默认行为 -->
  24. <a href="helo10086.cn" @click.prevent="this.url = $event.target.href"
  25. >vue2: 显示网址:
  26. </a>
  27. <span class="url">{{url}}</span>
  28. </p>
  29. <!-- 在父级上的同名事件,因为事件冒泡机制而被自动的调用了 -->
  30. <p onclick="alert('hello help!')">
  31. <!-- @click.stop: 阻止冒泡 -->
  32. <a
  33. href="helo10086.cn"
  34. @click.prevent.stop="this.url = $event.target.href"
  35. >vue3: 显示网址:
  36. </a>
  37. <span class="url">{{url}}</span>
  38. </p>
  39. </div>
  40. <script>
  41. const app = Vue.createApp({
  42. data() {
  43. return {
  44. url: null,
  45. };
  46. },
  47. methods: {
  48. showUrl(ev) {
  49. // 防止默认行为
  50. ev.preventDefault();
  51. console.log(ev === event);
  52. // this -> vue实例
  53. console.log(this);
  54. console.log(ev.target);
  55. this.url = ev.target.href;
  56. },
  57. },
  58. }).mount(".app");
  59. </script>
  60. </body>
  61. </html>

[http://help10086.cn/0114/demo1.html]

VUE 条件渲染与列表渲染

  • v-for , 对应原生的 for - of
  1. <!-- 列表渲染 -->
  2. <!DOCTYPE html>
  3. <html lang="zh-CN">
  4. <head>
  5. <meta charset="UTF-8" />
  6. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  7. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  8. <title>列表渲染</title>
  9. <script src="https://unpkg.com/vue@next"></script>
  10. </head>
  11. <body>
  12. <div class="app">
  13. <!-- array: v-for , 对应原生的 for - of -->
  14. <ul>
  15. <!-- 提高效率,一定要加 :key 为了借助diff算法,key必须选择一个永远唯一的值 -->
  16. <li v-for="(city,index) of cities" :key="index">{{index}}->{{city}}</li>
  17. </ul>
  18. <!-- obj: v-for -->
  19. <ul>
  20. <!-- prop -> property 属性 -->
  21. <li v-for="(item,prop,index) of user" :key="index">
  22. {{index}} ->{{prop}} => {{item}}
  23. </li>
  24. </ul>
  25. <!-- ArrayObj: v-for -->
  26. <ul>
  27. <li v-for="(user,index) of users" :key="index">
  28. {{user.name}}: ({{user.email}})
  29. </li>
  30. </ul>
  31. </div>
  32. <script>
  33. const app = Vue.createApp({
  34. data() {
  35. return {
  36. // array
  37. cities: ["tayninh", "nhontrach", "longthanh"],
  38. // object
  39. user: {
  40. name: "help",
  41. email: "help@foxmail.com",
  42. },
  43. // array of object
  44. users: [
  45. {
  46. name: "lan",
  47. email: "lan@foxmail.com",
  48. },
  49. {
  50. name: "hoang",
  51. email: "hoang@foxmail.com",
  52. },
  53. {
  54. name: "hope",
  55. email: "hope@foxmail.com",
  56. },
  57. ],
  58. };
  59. },
  60. }).mount(".app");
  61. </script>
  62. </body>
  63. </html>
  64. <!-- 条件渲染 -->
  65. <!DOCTYPE html>
  66. <html lang="zh-CN">
  67. <head>
  68. <meta charset="UTF-8" />
  69. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  70. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  71. <title>条件渲染</title>
  72. <script src="https://unpkg.com/vue@next"></script>
  73. </head>
  74. <body>
  75. <div class="app">
  76. <!-- if -->
  77. <p v-if="flag">{{message}}</p>
  78. <button @click="flag=!flag" v-text="flag ? '隐藏' : '显示'"></button>
  79. <!-- if -- if else -- if else -- else -->
  80. <p v-if="salary > 0 && salary < 2000">{{grade[1]}}</p>
  81. <p v-else-if="salary >= 2000 && salary < 6000">{{grade[2]}}</p>
  82. <p v-else-if="salary >= 6000 && salary < 10000">{{grade[3]}}</p>
  83. <p v-else-if="salary >= 10000 && salary < 15000">{{grade[4]}}</p>
  84. <p v-else-if="salary >= 15000">{{grade[5]}}</p>
  85. <p v-else>{{grade[0]}}</p>
  86. </div>
  87. <script>
  88. const app = Vue.createApp({
  89. data() {
  90. return {
  91. message: "20220116, 准备领完年终奖,回家过年吧!",
  92. flag: false,
  93. // 会员级别
  94. grade: [
  95. "操作工",
  96. "业务员",
  97. "主管",
  98. "一般管理",
  99. "中层管理",
  100. "高层管理",
  101. ],
  102. // 积分
  103. salary: 100000,
  104. };
  105. },
  106. }).mount(".app");
  107. </script>
  108. </body>
  109. </html>

列表渲染:[http://help10086.cn/0114/demo2.html]
条件渲染:[http://help10086.cn/0114/demo3.html]

VUE 计算属性与侦听器

  • 例生命周期, mounted: 当 vue 实例加载完成的时候会自动调用(onload)
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <script src="https://unpkg.com/vue@next"></script>
  8. <title>计算属性,侦听器属性</title>
  9. <style>
  10. table {
  11. width: 26em;
  12. text-align: center;
  13. border-collapse: collapse;
  14. }
  15. table caption {
  16. font-size: 1.5em;
  17. margin-bottom: 0.6em;
  18. }
  19. thead {
  20. background-color: lightcyan;
  21. }
  22. th,
  23. td {
  24. border: 1px solid #000;
  25. height: 2em;
  26. }
  27. </style>
  28. </head>
  29. <body>
  30. <div class="app">
  31. <table>
  32. <caption>
  33. 购物车
  34. </caption>
  35. <thead>
  36. <tr>
  37. <th>ID</th>
  38. <th>品名</th>
  39. <th>单价</th>
  40. <th>数量</th>
  41. <th>金额</th>
  42. </tr>
  43. </thead>
  44. <tbody>
  45. <tr>
  46. <td>20220116</td>
  47. <td>iphone 13</td>
  48. <td>{{price}}</td>
  49. <td><input type="number" v-model="num" style="width: 4em" /></td>
  50. <!-- <td>{{price * num}}</td> -->
  51. <td>{{payAmount}}</td>
  52. </tr>
  53. </tbody>
  54. </table>
  55. <!-- 侦听器来监听金额的变化,设置优惠价格:用户实际支付的钱 -->
  56. <!-- <p>实付金额: {{disAmount}}, 优惠了 : <span style="color: red">{{payAmount-disAmount}}</span></p> -->
  57. <p>
  58. 实付金额: {{disAmount}}, 优惠了 :
  59. <span style="color: #ff0000">{{difAmount}}</span>
  60. </p>
  61. </div>
  62. <script>
  63. const app = Vue.createApp({
  64. data() {
  65. return {
  66. price: 10000,
  67. num: 0,
  68. };
  69. },
  70. // 计算属性: 访问器属性
  71. computed: {
  72. payAmount: {
  73. get() {
  74. return this.price * this.num;
  75. },
  76. set(value) {
  77. // 这个通常用来做测试
  78. },
  79. },
  80. },
  81. // 侦听器属性
  82. watch: {
  83. // current: 新值/当前值, origin: 原值/旧值
  84. payAmount(current, origin) {
  85. console.log(current, origin);
  86. switch (true) {
  87. case current > 10000 && current < 20000:
  88. this.disAmount = this.payAmount * 0.99;
  89. break;
  90. case current >= 20000 && current < 30000:
  91. this.disAmount = this.payAmount * 0.98;
  92. break;
  93. case current >= 30000 && current < 40000:
  94. this.disAmount = this.payAmount * 0.97;
  95. case current >= 40000 && current < 50000:
  96. this.disAmount = this.payAmount * 0.96;
  97. break;
  98. case current > 50000:
  99. this.disAmount = this.payAmount * 0.95;
  100. break;
  101. default:
  102. this.disAmount = this.payAmount;
  103. }
  104. this.difAmount = this.payAmount - this.disAmount;
  105. },
  106. },
  107. // 实例生命周期, mounted: 当vue实例加载完成的时候会自动调用(onload)
  108. mounted() {
  109. this.num = 1;
  110. },
  111. }).mount(".app");
  112. </script>
  113. </body>
  114. </html>

[http://help10086.cn/0114/demo5.html]

VUE 组件与组件之间的通信

  • 组件,vue 指令本质是自定义属性
  • vue 组件本质就是自定义标签
  • 子组件传参:自定义属性
  • 监听子组件: $emit(自定义事件, 向父组件传递的参数[可选])
  1. <!-- VUE组件 -->
  2. <!DOCTYPE html>
  3. <html lang="zh-CN">
  4. <head>
  5. <meta charset="UTF-8" />
  6. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  7. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  8. <title>组件:全局组件</title>
  9. <script src="https://unpkg.com/vue@next"></script>
  10. </head>
  11. <body>
  12. <div class="app">
  13. <!-- vue指令 -> 自定义属性 -->
  14. <div v-text="'hello'"></div>
  15. <!-- vue组件 -> 自定义标签 -->
  16. <button-counter></button-counter>
  17. </div>
  18. <template id="counter">
  19. <button @click="count++">点赞: {{count}}</button>
  20. </template>
  21. <script>
  22. // 1. 创建实例
  23. const app = Vue.createApp({});
  24. // 2. 注册组件
  25. app.component("ButtonCounter", {
  26. template: "#counter",
  27. data() {
  28. return {
  29. count: 0,
  30. };
  31. },
  32. });
  33. // 3. 绑定挂载点
  34. app.mount(".app");
  35. </script>
  36. </body>
  37. </html>
  38. <!-- 子组件传参 -->
  39. <!DOCTYPE html>
  40. <html lang="zh-CN">
  41. <head>
  42. <meta charset="UTF-8" />
  43. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  44. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  45. <title>子组件传参</title>
  46. <script src="https://unpkg.com/vue@next"></script>
  47. </head>
  48. <body>
  49. <div class="app">
  50. <button-counter username="admin" email="admin@qq.com"></button-counter>
  51. </div>
  52. <template id="counter">
  53. <button @click="count++">点赞: {{count}}</button>
  54. <p>用户: {{username}}</p>
  55. <p>邮箱: {{email}}</p>
  56. </template>
  57. <script>
  58. // 1. 创建实例
  59. const app = Vue.createApp({});
  60. // 2. 注册组件
  61. app.component("ButtonCounter", {
  62. // 自定义属性
  63. props: ["username", "email"],
  64. template: "#counter",
  65. data() {
  66. return {
  67. count: 0,
  68. };
  69. },
  70. });
  71. // 3. 绑定挂载点
  72. app.mount(".app");
  73. </script>
  74. </body>
  75. </html>
  76. <!-- 监听子组件事件 -->
  77. <!DOCTYPE html>
  78. <html lang="zh-CN">
  79. <head>
  80. <meta charset="UTF-8" />
  81. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  82. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  83. <title>监听子组件事件</title>
  84. <script src="https://unpkg.com/vue@next"></script>
  85. </head>
  86. <body>
  87. <div class="app">
  88. <button-counter
  89. username="help"
  90. email="help10086@foxmail.com"
  91. @review-count="review"
  92. ></button-counter>
  93. </div>
  94. <template id="counter">
  95. <button @click="count++">点赞: {{count}}</button>
  96. <p>用户: {{username}}</p>
  97. <p>邮箱: {{email}}</p>
  98. <!-- 发布订阅 -->
  99. <!-- $emit(自定义事件, 向父组件传递的参数[可选]) -->
  100. <button @click="$emit('reviewCount', this.count)">评价</button>
  101. </template>
  102. <script>
  103. // 1. 创建实例
  104. const app = Vue.createApp({
  105. methods: {
  106. review(count) {
  107. console.log(count);
  108. if (count >= 20) {
  109. alert("感谢家人的支持!");
  110. }
  111. },
  112. },
  113. });
  114. // 2. 注册组件
  115. app.component("ButtonCounter", {
  116. props: ["username", "email"],
  117. template: "#counter",
  118. data() {
  119. return {
  120. count: 0,
  121. };
  122. },
  123. });
  124. // 3. 绑定挂载点
  125. app.mount(".app");
  126. // 1. 向子组传传参: props: [....]
  127. // 2. 子组件向父组通信:
  128. // 2.1 子组件: $emit(customEvent, ...args)
  129. // 2.2 父组件: @customEvent(...args)
  130. </script>
  131. </body>
  132. </html>

[http://help10086.cn/0114/demo7.html]
[http://help10086.cn/0114/demo8.html]

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议