事件处理与组件基础

一、事件处理和表单输入绑定

1.事件处理

(1)概念:在 Vue.js中,你可以使用 v-on 指令监听 DOM 事件,并在事件触发时执行 JavaScript 代码。v-on 可以简写为@

(2)示例:

HTML

<div id="app">
  <button v-on:click="counter += 1">点击增加1</button>
  <p>{{ counter }}</p>

  <button @click="greet">点我打招呼</button>
  <p>{{ message }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  var app = new Vue({
    el: '#app',
    data: {
      counter: 0,
      message: '欢迎!'
    },
    methods: {
      greet: function (event) {
        // `this` 在方法中指向 Vue 实例
        alert('你好,' + this.message + '!')
        // `event` 是原生 DOM 事件
        if (event) {
          event.target.innerHTML = '已打招呼'
        }
      }
    }
  })
</script>

2.事件修饰符

(1)Vue提供了事件修饰符来处理事件的细节,比如阻止冒泡、阻止默认行为。

(2)常用的修饰符有:.stop 、.prevent 、.capture 、 .self

(3)示例:

HTML

<a @click.stop="doThis"></a>

<form @submit.prevent="onSubmit"></form>

3.表单输入绑定

(1)概念:v-model 指令用于在表单控件上创建双向数据绑定,它会根据控件 1 类型自动更新数据

(2)示例 :

HTML

<div id="app-form">
  <p>你的名字:<input v-model="name"></p>
  <p>你输入的名字是: {{ name }}</p>
  
  <p>你最喜欢的框架:</p>
  <input type="checkbox" id="vue" value="Vue" v-model="checkedNames">
  <label for="vue">Vue</label>
  <input type="checkbox" id="react" value="React" v-model="checkedNames">
  <label for="react">React</label>
  <p>你喜欢的框架有: {{ checkedNames }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  new Vue({
    el: '#app-form',
    data: {
      name: '',
      checkedNames: []
    }
  })
</script>

二、组件基础:可复用的 vue 实例,它拥有自己的模板、逻辑和样式

1.组件注册:要使用组件,首先需要注册它。可以注册全局组件或局部组件

(1)全局组件示例:

HTML

<div id="app">
  <my-component></my-component>
</div>

<script>
  // 全局注册,可以在任何 Vue 实例的模板中使用
  Vue.component('my-component', {
    template: '<div>一个自定义组件!</div>'
  })

  new Vue({ el: '#app' })
</script>

(2)局部注册示例

HTML

<div id="app">
  <my-local-component></my-local-component>
</div>

<script>
  var ChildComponent = {
    template: '<div>一个局部组件!</div>'
  }

  new Vue({
    el: '#app',
    components: {
      'my-local-component': ChildComponent
    }
  })
</script>

2.组件的 data 必须是一个函数

(1)概念:在组件中,data 必须是一个函数,并且返回一个对象。为了确保每个组件实例都有自己独立的数据副本

(2)示例

JavaScript

Vue.component('button-counter', {
  data: function () {
    return {
      count: 0 // 每个组件实例的 count 都是独立的
    }
  },
  template: '<button @click="count++">你点击了 {{ count }} 次</button>'
})

三、组件通信(props 和 events)

1.概念:组件通信主要分为父组件通信和子组件向父组件通信两种方式

2.父组件向子组件传递数据:使用 props

(1)概念:props 是子组件用来接收父组件传递来的数据的自定义属性。props 是单向的,父组件数据更新时,会传递给子组件,但子组件不能直接修改 props 的值

(2)示例:

HTML

<div id="app">
  <child-component my-prop-title="来自父组件的标题"></child-component>
</div>

<script>
  // 子组件定义
  var ChildComponent = {
    props: ['myPropTitle'],
    template: '<div><h2>{{ myPropTitle }}</h2></div>'
  };

  // 父组件实例
  new Vue({
    el: '#app',
    components: {
      'child-component': ChildComponent
    }
  });
</script>

3.子组件向父组件发送消息:使用 events

(1)概念:子组件不能直接修改父组件的数据,但可以通过 $emit 方法触发一个自定义事件,父组件则通过 v-on (或@)监听这个事件,从而做出响应

(2)示例:

HTML

<div id="app-event">
  <p>父组件计数器: {{ total }}</p>
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>

<script>
  // 子组件定义
  Vue.component('button-counter', {
    template: '<button @click="incrementCounter">增加</button>',
    data: function () {
      return {
        counter: 0
      }
    },
    methods: {
      incrementCounter: function () {
        this.counter += 1
        this.$emit('increment') // 子组件触发 `increment` 事件
      }
    }
  });

  // 父组件实例
  new Vue({
    el: '#app-event',
    data: {
      total: 0
    },
    methods: {
      incrementTotal: function () {
        this.total += 1
      }
    }
  });
</script>

四、实践项目:Vue 待办事项应用

1.应用功能:

(1)输入框:用户可以在输入框中输入新的待办事项

(2)添加按钮:点击按钮,将输入框中的事项添加到列表中

(3)列表展示:使用 v-for 将所有待办事项展示出来

(4)删除功能:每个待办事项旁边有一个删除按钮,点击后可以从列表中移除该事项

(5)组件化:将单个待办事项(包含文本和删除按钮)封装成一个独立的组件

2.步骤

(1)创建 Vue 实例:在 data 中定义一个待办事项数组,例如 todos:[{  id:1,text:  '学习 Vue'}]

(2)构建组件:创建一个名为 todo-item 的子组件,它通过 props 接收待办事项对象

(3)组件通信:在 todo-item 组件内部,点击删除按钮时,通过 $emit 触发一个自定义事件,将该事项的 ID 传给父组件

(4)父组件处理:父组件监听子组件的事件,并根据传入的 ID 从 todos 数组中移除该事项

3.示例:

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue 待办事项应用</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <style>
        .todo-item {
            padding: 8px;
            border-bottom: 1px solid #eee;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .todo-item:last-child {
            border-bottom: none;
        }
        .remove-btn {
            background-color: #f44336;
            color: white;
            border: none;
            padding: 5px 10px;
            cursor: pointer;
        }
    </style>
</head>
<body>

<div id="app">
    <h2>我的待办事项</h2>
    <div>
        <input type="text" v-model="newTodoText" @keyup.enter="addNewTodo">
        <button @click="addNewTodo">添加</button>
    </div>
    
    <ul>
        <todo-item 
            v-for="todo in todos"
            :key="todo.id"
            :todo-prop="todo"
            @remove="removeTodo"
        ></todo-item>
    </ul>
</div>

<script>
    // 定义子组件
    Vue.component('todo-item', {
        // 使用 props 接收父组件传递过来的数据
        props: ['todoProp'],
        template: `
            <li class="todo-item">
                <span>{{ todoProp.text }}</span>
                <button class="remove-btn" @click="$emit('remove', todoProp.id)">删除</button>
            </li>
        `
    });

    // 创建 Vue 根实例
    new Vue({
        el: '#app',
        data: {
            newTodoText: '',
            todos: [
                { id: 1, text: '学习 Vue 基础' },
                { id: 2, text: '练习组件通信' },
                { id: 3, text: '完成待办事项应用' }
            ],
            nextTodoId: 4
        },
        methods: {
            addNewTodo: function() {
                if (this.newTodoText.trim() === '') return;
                
                this.todos.push({
                    id: this.nextTodoId++,
                    text: this.newTodoText
                });
                this.newTodoText = ''; // 清空输入框
            },
            // 父组件的方法:监听子组件的 'remove' 事件,并处理删除逻辑
            removeTodo: function(idToRemove) {
                // 使用 filter 过滤出不等于要删除 id 的事项
                this.todos = this.todos.filter(todo => todo.id !== idToRemove);
            }
        }
    });
</script>

</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值