前端4 事件处理器 | 青训营

44 阅读4分钟

事件处理方法

然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在组件属性值里是不可行的。因此@事件还可以接收一个需要调用的方法名称。

     <template>
         <view>
             <!-- `greet` 是在下面定义的方法名 -->
             <button @click="greet">Greet</button>
         </view>
     </template>
     <script>
         export default {
             data() {
                 return {
                     name: 'Vue.js'
                 }
             },
             // 在 `methods` 对象中定义方法
             methods: {
                 greet(event){
                     // `event` 是原生 DOM 事件
                     console.log(event);
                     uni.showToast({
                         title: 'Hello ' + this.name + '!'
                     });
                 }
             }
         }
     </script>

内联处理器中的方法

除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:

     <template>
         <view>
             <button @click="say('hi')">Say hi</button>
             <button @click="say('what')">Say what</button>
         </view>
     </template>
     <script>
         export default {
             methods: {
                 say(message) {
                     uni.showToast({
                         title: message
                     });
                 }
             }
         }
     </script>

事件处理器

事件处理程序中可以有多个方法,这些方法由逗号运算符分隔:

     <template>
         <view>
             <!-- 这两个 one() 和 two() 将执行按钮点击事件 -->
             <button @click="one($event); two($event)">
               Submit
             </button>
         </view>
     </template>
     <script>
         export default {
             methods: {
                 one(event) {
                     // first handler logic...
                     console.log("event1: ",event);
                 },
                 two(event) {
                     // second handler logic...
                     console.log("event2: ",event);
                 }
             }
         }
     </script>

事件修饰符

修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 @事件对于触发的事件调用 event.preventDefault()

@事件(v-on)提供了事件修饰符:

  • .stop: 各平台均支持, 使用时会阻止事件冒泡,在非 H5 端同时也会阻止事件的默认行为
  • .prevent: 仅在 H5 平台支持
  • .capture: 仅在 H5 平台支持
  • .self: 仅在 H5 平台支持
  • .once: 仅在 H5 平台支持
  • .passive: 仅在 H5 平台支持
     <!-- 阻止单击事件继续传播 -->
     <view @click.stop="doThis"></view>

复制代码

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 @click.prevent.self 会阻止所有的点击,而 @click.self.prevent 只会阻止对元素自身的点击。

注意

  • uni-app x 暂不支持。
  • 为兼容各端,事件需使用 @ 的方式绑定,请勿使用小程序端的 bindcatch 进行事件绑定;也不能在 JS 中使用event.preventDefault()event.stopPropagation()方法。
  • 若需要禁止蒙版下的页面滚动,可使用 @touchmove.stop.prevent="moveHandle"moveHandle 可以用来处理 touchmove 的事件,也可以是一个空函数。
     <view class="mask" @touchmove.stop.prevent="moveHandle"></view>
  • 按键修饰符:uni-app 运行在手机端,没有键盘事件,所以不支持按键修饰符。

使用 v-on 或 @ 有几个好处

  1. 扫一眼 template 模板便能轻松定位在 JavaScript 代码里对应的方法。
  2. 因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。
  3. 当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理它们。

事件映射表

 // 事件映射表,左侧为 WEB 事件,右侧为 ``uni-app`` 对应事件
     {
         click: 'tap',
         touchstart: 'touchstart',
         touchmove: 'touchmove',
         touchcancel: 'touchcancel',
         touchend: 'touchend',
         tap: 'tap',
         longtap: 'longtap', //推荐使用longpress代替
         input: 'input',
         change: 'change',
         submit: 'submit',
         blur: 'blur',
         focus: 'focus',
         reset: 'reset',
         confirm: 'confirm',
         columnchange: 'columnchange',
         linechange: 'linechange',
         error: 'error',
         scrolltoupper: 'scrolltoupper',
         scrolltolower: 'scrolltolower',
         scroll: 'scroll'
     }

表单输入绑定

v-model

你可以用 v-model 指令在表单 inputtextareaselect 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

v-model 会忽略所有表单元素的 valuecheckedselected attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。

在下面的示例中,输入框通过v-model绑定了message,用户在输入框里输入内容时,这个内容会实施赋值给message。当然在代码里为message赋值也会实时同步到界面上input里。这就是双向绑定。

     <template>
         <view>
             <input v-model="message" placeholder="edit me">
             <text>Message is: {{ message }}</text>
         </view>
     </template>
     <script>
         export default {
             data() {
                 return {
                     message:""
                 }
             }
         }
     </script>

uni-app表单组件

建议开发过程中直接使用 uni-app表单组件

用法示例:
  • H5 的 select 标签用 picker 组件进行代替
     <template>
         <view>
             <picker @change="bindPickerChange" :value="index" :range="array">
                 <view class="picker">
                     当前选择:{{array[index]}}
                 </view>
             </picker>
         </view>
     </template>
     <script>
         export default {
             data() {
                 return {
                     index: 0,
                     array: ['A', 'B', 'C']
                 }
             },
             methods: {
                 bindPickerChange(e) {
                     console.log(e)
                     this.index = e.detail.value
                 }
             }
         }
     </script>
  • 表单元素 radioradio-group 组件进行代替计算属性的 getter

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如,有一个嵌套数组对象:

     data() {
         return {
             author: {
                 name: 'John Doe',
                 books: [
                     'Vue 2 - Advanced Guide',
                     'Vue 3 - Basic Guide',
                     'Vue 4 - The Mystery'
                 ]
             }
         }
     }

我们想根据 author 是否已经有一些书来显示不同的消息,可以使用模板内的表达式

     <view>
         <view>Has published books:</view>
         <view>{{ author.books.length > 0 ? 'Yes' : 'No' }}</view>
     </view>

此时,模板不再是简单的和声明性的。你必须先看一下它,然后才能意识到它执行的计算取决于 author.books。如果要在模板中多次包含此计算,则问题会变得更糟。