如何在 vue.js 中使用 @click 触发两个事件

Posted

技术标签:

【中文标题】如何在 vue.js 中使用 @click 触发两个事件【英文标题】:how to trigger two events with @click in vue.js 【发布时间】:2019-12-12 01:00:12 【问题描述】:

我正在使用 Vue.js、Vuetify 和 Firebase 构建一个任务管理器应用程序。单击“添加新注释”会打开一个 Vuetify 对话框,提示用户输入数据。单击保存关闭对话框,同时将输入的数据提交并呈现到屏幕上的任务卡。呈现的任务卡包括一个“查看/编辑”按钮,单击该按钮会打开第二个对话框,供用户查看和编辑数据。我的问题是编辑。我目前使用触发模式的@click 事件设置了“查看/编辑”按钮。我需要此查看/编辑@click 事件来触发将选定任务卡中的数据绑定到第二个对话框的函数,然后可以对其进行编辑。我试图通过在“查看/编辑”按钮中设置@click事件来实现这一点,如下所示:

<v-btn color="primary" dark @click.stop="dialogUpdate = true; editTodo(todo)">
   View/Edit
  </v-btn>

...可以看到,@click事件包含“dialog = true”,用于切换Vuetify对话框,以及“editTodo(todo)”,触发绑定输入数据的editTodo函数到第二个对话框。这目前工作正常,但我的问题是我不清楚我是否应该真正为单击事件添加两个功能。我研究过的其他 Stack Overflow 帖子表明这不是一个好的做法。如果这是错误的,那么您建议如何配置“查看/编辑”按钮,以便打开第二个对话框也触发 editTodo 功能?我的完整组件如下。谢谢!

<template>
  <div id="app" data-app>

    <v-layout justify-center>
      <v-btn color="primary" dark @click.stop="dialog = true">
        Add New Note
      </v-btn>

      <v-dialog v-model="dialog" max->
        <v-card color="#f9efaf">
          <v-form @submit.prevent="addTodo">
            <v-card-text>
              <textarea-autosize v-model="newTitle" :min- placeholder="add title"></textarea-autosize>
              <textarea-autosize v-model="newTodo" type="text" style="width: 100%" :min- placeholder="add note"></textarea-autosize>
            </v-card-text>
            <v-btn type="submit" color="green darken-1" text @click="dialog = false">
              Add
            </v-btn>
          </v-form>
          <v-card-actions>
            <v-spacer></v-spacer>
          </v-card-actions>
        </v-card>
      </v-dialog>

      <v-dialog v-model="dialogUpdate" max->
        <v-card color="#f9efaf">
          <v-form @submit.prevent="updateTodoText">
            <v-card-text>
              <textarea-autosize v-model="todoEditTitle" :min- placeholder="add title"></textarea-autosize>
              <textarea-autosize v-model="todoEditText" type="text" :min- placeholder="add note"></textarea-autosize>
            </v-card-text>
            <v-btn type="submit" color="green darken-1" text @click="dialogUpdate = false">
              Update
            </v-btn>
          </v-form>
          <v-card-actions>
            <v-spacer></v-spacer>
          </v-card-actions>
        </v-card>
      </v-dialog>
    </v-layout>

    <v-container>
      <v-flex md12 class="elevation-0">
       <v-layout wrap>
         <v-flex md3 v-for="todo in todos" :key="todo.id">
           <v-card color="#f9efaf" class="card-container">
             <textarea-autosize v-model="todo.title" class="todo-text" readonly style="width: 60%"></textarea-autosize>
             <textarea-autosize v-model="todo.text" class="todo-text" readonly></textarea-autosize>
              <v-btn @click="deleteTodo(todo.id)">Delete</v-btn>
              <v-btn color="primary" dark @click.stop="dialogUpdate = true; editTodo(todo)">
              View/Edit
            </v-btn>
          </v-card>
         </v-flex>
       </v-layout>
      </v-flex>
    </v-container>
  </div>
</template>

<script>
import  todosCollection  from './firebase';
import  mapState  from 'vuex'
export default 
  name: 'app',
  created() 
    this.getData();
  ,
  data () 
    return 
      todos: [],
      newTitle: '',
      newTodo: '',
      currentlyEditing: null,
      todoEditTitle: '',
      todoEditText: '',
      dialog: false,
      dialogUpdate: false
    
  ,
  methods: 
    getData()
      const todos = []
      todosCollection.orderBy('createdAt').get()
      .then(snapshot => 
        snapshot.forEach(doc => 
          let userData = doc.data()
          userData.id = doc.id
          todos.push(userData)
        )
        this.todos = todos
      )
    ,
    addTodo() 
      todosCollection.add(
        title: this.newTitle,
        text: this.newTodo,
        createdAt: new Date()
      )
      .then(() => 
        this.newTitle = '',
        this.newTodo = ''
      )
    ,
    deleteTodo(id) 
      todosCollection.doc(id).delete()
      .then(() => 
        console.log('Document successfully deleted')
      )
      .then(() => 
        this.getData()
      )
    ,
    editTodo(todo) 
      this.currentlyEditing = todo.id
      this.todoEditText = todo.text
      this.todoEditTitle = todo.title
    ,
    updateTodoText() 
      todosCollection.doc(this.currentlyEditing).update(
        text: this.todoEditText,
        title: this.todoEditTitle
      )
      .then(() => 
        this.getData()
      )
      .catch(function(error) 
        console.error("Error updating document text: ", error);
      );
      this.currentlyEditing = null;
      this.todoEditText = '';
      this.todoEditTitle = '';
    
  

</script>

<style>
body 
  margin: 0;
  padding: 0;

#app 
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
  margin: 0;
  padding: 0;

.card-container 
  margin: 10px;
  padding: 10px;

</style>

解决方案:

 <v-btn color="primary" dark @click.stop="editTodo(todo)">
    View/Edit
 </v-btn>


 editTodo(todo) 
   this.dialogUpdate = true
   this.currentlyEditing = todo.id
   this.todoEditText = todo.text
   this.todoEditTitle = todo.title
 ,

【问题讨论】:

将其包装在一个方法中并调用它。 这行得通。谢谢!我没有想到可以将“dialogUpdate = true”添加到方法中。我将在上面添加我的解决方案。非常感谢! 您应该发布自己的解决方案作为答案并接受它:) 【参考方案1】:

这就是解决方案。 dialogUpdate = true 应该包含在 editTodo() 函数中,以及用于将输入数据绑定到第二个对话框的代码。

<v-btn color="primary" dark @click.stop="editTodo(todo)">
    View/Edit
 </v-btn>


 editTodo(todo) 
   this.dialogUpdate = true
   this.currentlyEditing = todo.id
   this.todoEditText = todo.text
   this.todoEditTitle = todo.title
 ,

【讨论】:

以上是关于如何在 vue.js 中使用 @click 触发两个事件的主要内容,如果未能解决你的问题,请参考以下文章

JEST 不会触发模拟函数 Vue js

如何在使用 Vue.js 触发任何事件时创建新组件?

Fastclick 导致click事件触发两次的问题,fastclickclick

如何在按钮@click [VUE JS]上连续调用函数

Vue.js:如何在组件初始化时触发观察器函数

在“点击,点击”事件触发两次。如何避免?