第二篇 Vue指令

v-model 是 Vue.js 中的一个指令,它用于在 input、select、textarea 等表单控件元素上创建数据双向绑定。双向绑定意味着它不仅将数

据从 Vue 实例绑定到表单元素,而且还会将表单元素的更新双向反映回 Vue 实例的数据。

在 Vue 3 中,v-model 可以和以下输入元素一起使用:

text radio checkbox select

html 复制代码
<template>
    <div>
        <p v-text="msg"></p>
        <p>疑是{{msg}}地上霜</p>
        <input type="text" v-model="username"/>
        <h3>{{username}}</h3>
        <!-- v-model实现数据双向绑定  本质基于MVVM设计思想
            MVVM: 
                M:model 数据模型
                V: view   视图
                VM:ViewModel  视图和模型(中介)
        -->
        <input type="button" value="修改数据" @click="updateUsername()">
    </div>
</template>
<script setup>

    import {ref,reactive} from 'vue';

    let msg = ref("白头并非雪可替,");
    let username = ref("")

    //自定义函数
    const updateUsername = () => {
        username.value = "圆圆";
    }
</script>

1、MVVM思想

2、v-bind

v-bind介绍

在Vue 3中,v-bind指令用于绑定属性到表达式。简单来说,它可以绑定一个或多个属性值到指定的元素。

html 复制代码
<template>
    <!-- 
        v-bind:实现给元素属性绑定一个值
         语法: v-bind:属性名="值" ,v-bind指令可以省略  :(冒号)属性名="数据" 比如: :src="值"
    -->
    <img v-bind:src="imgPath" :alt="altTxt" :title="altTxt" :ykjAttribute="altTxt">
    <input type="button" value="更改" @click="updateImagePath()">
</template>
<script setup>

import {ref,reactive} from 'vue';

//定义数组,数组中存放图片路径
const imgs = reactive(["./assets/img/gz2.jpg","./assets/img/aa.jpg"])
//模型显示图片
let imgPath = ref(imgs[0]);

let altTxt = ref("加载失败");

//电话号码
let telphone = ref("");

//自定义函数,实现更新图片地址
const updateImagePath = () => {
    imgPath.value = imgs[1];
}

</script>

3、v-on

v-on介绍

在Vue 3中,v-on指令用于绑定事件监听器。它可以简写为@符号。

html 复制代码
<template>
    <!-- 
        v-on: 该指令作用用于对元素进行事件绑定   
            语法: <p v-on:click="函数名称"></p>
            v-on指令也可以进行简写,v-on: 可以简写为@符号。比如: @click="函数名"
    -->
    <input type="text" v-model="telphone" @change="getVal()">
</template>
<script setup>

import {ref,reactive} from 'vue';

//获取用户在input中获取数据
const getVal = () => {
    console.log("telphone = " + telphone.value);
}

</script>

4.v-for

v-for 的基本用法

v-for 是 Vue.js 中用于循环渲染列表数据的指令。通过 v-for 可以遍历数组或对象,并为每一项生成对应的 DOM 元素。

语法格式:

javascript 复制代码
<template>
  <div v-for="(item, index) in items" :key="index">
    {{ item }}
  </div>
</template>

items 是数据源,item 是当前遍历的项,index 是当前项的索引(可选)。:key 是必须的,用于优化渲染性能。

遍历数组

v-for 最常用于遍历数组,支持获取当前项和索引:

javascript 复制代码
<template>
  <ul>
    <li v-for="(fruit, index) in fruits" :key="index">
      {{ index }}. {{ fruit }}
    </li>
  </ul>
</template>

<script>
export default {
  data() {
    return {
      fruits: ['Apple', 'Banana', 'Orange']
    }
  }
}
</script>

遍历对象

v-for 也可以遍历对象的属性,支持获取属性值、键名和索引:

javascript 复制代码
<template>
  <ul>
    <li v-for="(value, key, index) in user" :key="key">
      {{ index }}. {{ key }}: {{ value }}
    </li>
  </ul>
</template>

<script>
export default {
  data() {
    return {
      user: {
        name: 'John',
        age: 30,
        gender: 'male'
      }
    }
  }
}
</script>

使用 key 的重要性

v-for 添加 :key 是必要的,它帮助 Vue 识别节点的唯一性,优化 DOM 更新。通常使用唯一 ID 或索引作为 key:

javascript 复制代码
<template>
  <div v-for="item in items" :key="item.id">
    {{ item.name }}
  </div>
</template>

在组件中使用 v-for

在组件中使用 v-for 时,需要通过 props 将数据传递给子组件:

javascript 复制代码
<template>
  <ChildComponent v-for="item in items" :key="item.id" :item="item" />
</template>

性能优化

避免在 v-for 中使用复杂计算或方法调用,应在 computed 中预先处理数据:

javascript 复制代码
<template>
  <div v-for="item in filteredItems" :key="item.id">
    {{ item.name }}
  </div>
</template>

<script>
export default {
  computed: {
    filteredItems() {
      return this.items.filter(item => item.active)
    }
  }
}
</script>

遍历数字或字符串

v-for 也可以直接遍历数字或字符串:

javascript 复制代码
<template>
  <span v-for="n in 5" :key="n">{{ n }}</span>
</template>

结合 v-if 使用

v-forv-if 一起使用时,v-for 的优先级更高。建议通过计算属性过滤数据,而非在模板中同时使用两者。

5.v-model

v-model 的基本用法

v-model 是 Vue.js 中用于实现表单输入和应用状态双向绑定的指令。它本质上是一个语法糖,结合了 v-bindv-on 的功能。v-model 会根据表单元素的类型自动选择正确的方式更新数据。

html 复制代码
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>

v-model 的工作原理

v-model 在不同的表单元素上有不同的实现方式:

  • 对于文本输入框 (<input type="text">),使用 value 属性和 input 事件
  • 对于复选框 (<input type="checkbox">),使用 checked 属性和 change 事件
  • 对于单选按钮 (<input type="radio">),使用 checked 属性和 change 事件
  • 对于选择框 (<select>),使用 value 属性和 change 事件

v-model 的修饰符

v-model 提供了一些有用的修饰符来改变默认行为:

  • .lazy - 将 input 事件改为 change 事件触发更新
  • .number - 将用户输入转为数字类型
  • .trim - 自动去除用户输入的首尾空格
html 复制代码
<input v-model.lazy="msg">
<input v-model.number="age" type="number">
<input v-model.trim="msg">

自定义组件中使用 v-model

在自定义组件中实现 v-model 需要定义一个 model 选项,指定 propevent

javascript 复制代码
Vue.component('custom-input', {
  props: ['value'],
  model: {
    prop: 'value',
    event: 'input'
  },
  template: `
    <input
      :value="value"
      @input="$emit('input', $event.target.value)"
    >
  `
})

v-model 与 Vue 3 的变更

在 Vue 3 中,v-model 有了一些变化:

  • 默认使用 modelValue 作为 prop,update:modelValue 作为事件
  • 移除了 .sync 修饰符,可以用多个 v-model 替代
  • 自定义修饰符可以通过 modelModifiers prop 访问
javascript 复制代码
app.component('custom-input', {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:modelValue'],
  template: `
    <input 
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)"
    >
  `
})

v-model 的高级用法

在复杂场景下,v-model 可以结合计算属性使用:

javascript 复制代码
computed: {
  fullName: {
    get() {
      return this.firstName + ' ' + this.lastName
    },
    set(newValue) {
      const names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
html 复制代码
<input v-model="fullName">

v-model 与表单验证

v-model 可以方便地与表单验证库如 VeeValidate 结合使用:

html 复制代码
<validation-provider v-slot="{ errors }" rules="required|email">
  <input v-model="email" type="email">
  <span>{{ errors[0] }}</span>
</validation-provider>

6.vue的生命周期

vue 的生命周期

Vue 的生命周期是指 Vue 实例从创建到销毁的整个过程,每个阶段会触发特定的钩子函数,开发者可以在这些钩子函数中执行自定义逻辑。

生命周期钩子函数

beforeCreate

在实例初始化之后,数据观测 (data observer) 和事件配置之前被调用。此时无法访问 data、computed、methods 等属性。

created

实例创建完成后调用,此时可以访问 data、computed、methods 等属性,但 DOM 还未生成,无法操作 DOM。

beforeMount

在挂载开始之前被调用,相关的 render 函数首次被调用,但 DOM 还未渲染完成。

mounted

实例挂载完成后调用,此时 DOM 已经渲染完成,可以操作 DOM。通常在此阶段发起异步请求或初始化第三方库。

beforeUpdate

数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。可以在更新前访问现有的 DOM。

updated

数据更新导致虚拟 DOM 重新渲染和打补丁后调用。此时 DOM 已经更新,避免在此阶段修改数据,可能导致无限循环。

beforeDestroy

实例销毁之前调用,此时实例仍然完全可用。适合清理定时器、取消事件监听等操作。

destroyed

实例销毁后调用,所有的事件监听器和子实例被移除。此时无法再访问实例的任何属性和方法。

生命周期图示

以下是一个简化的 Vue 生命周期流程:

  1. 初始化阶段:beforeCreatecreated
  2. 挂载阶段:beforeMountmounted
  3. 更新阶段:beforeUpdateupdated
  4. 销毁阶段:beforeDestroydestroyed

代码示例

javascript 复制代码
export default {
  data() {
    return {
      message: 'Hello Vue!'
    }
  },
  beforeCreate() {
    console.log('beforeCreate')
  },
  created() {
    console.log('created')
  },
  beforeMount() {
    console.log('beforeMount')
  },
  mounted() {
    console.log('mounted')
  },
  beforeUpdate() {
    console.log('beforeUpdate')
  },
  updated() {
    console.log('updated')
  },
  beforeDestroy() {
    console.log('beforeDestroy')
  },
  destroyed() {
    console.log('destroyed')
  }
}

注意事项

  • 避免在 updated 中修改数据,可能导致无限循环。
  • 异步操作(如 API 请求)通常在 createdmounted 中执行。
  • 使用 beforeDestroy 清理资源,防止内存泄漏。

7.组件之间的参数传递

组件间参数传递的方法

在软件开发中,组件间参数传递是常见的需求,不同场景下可采用不同的方法。以下是几种常见的参数传递方式:

props传递(适用于父子组件) 父组件通过props向子组件传递数据,子组件通过props接收数据。这是Vue和React等框架中最基础的传递方式。

复制代码
// 父组件
<ChildComponent :message="parentMessage" />

// 子组件
props: ['message']

事件发射(子向父通信) 子组件通过$emit触发事件,父组件通过v-on监听事件并处理数据。

复制代码
// 子组件
this.$emit('update', newValue)

// 父组件
<ChildComponent @update="handleUpdate" />

provide/inject(跨层级传递) 祖先组件通过provide提供数据,后代组件通过inject注入数据,适合深层嵌套组件通信。

复制代码
// 祖先组件
provide() {
  return {
    theme: this.themeData
  }
}

// 后代组件
inject: ['theme']

Vuex/Redux状态管理 通过集中式状态管理工具实现全局状态共享,适合大型应用中多个组件需要访问同一状态的情况。

复制代码
// 存储状态
state: {
  count: 0
}

// 组件中访问
this.$store.state.count

Event Bus事件总线 创建中央事件总线实现任意组件间通信,适合小型应用或简单场景。

复制代码
// 创建总线
const bus = new Vue()

// 发送事件
bus.$emit('event-name', data)

// 接收事件
bus.$on('event-name', data => {})

URL参数传递 通过路由参数或查询字符串在页面间传递数据,适合需要保持状态的页面跳转。

复制代码
// 路由配置
{ path: '/user/:id' }

// 组件获取
this.$route.params.id

本地存储 使用localStorage或sessionStorage在浏览器端持久化数据,适合需要跨会话保持的数据。

复制代码
// 存储数据
localStorage.setItem('key', value)

// 获取数据
localStorage.getItem('key')

选择传递方法的考虑因素

组件关系 父子组件优先使用props/$emit,跨层级组件考虑provide/inject,无关组件使用全局状态管理或事件总线。

数据时效性 临时数据使用事件传递,持久数据使用状态管理或本地存储。

应用规模 小型应用可用事件总线,大型应用建议采用Vuex/Redux等状态管理工具。

数据敏感性 敏感数据避免通过URL或本地存储传递,应考虑更安全的通信方式。

相关推荐
frontend丶CV2 小时前
useMemo
前端·react.js
明月_清风2 小时前
基于 node-rtsp-stream 的 Web 直播方案详解
前端
DEMO派2 小时前
前端处理用户离开当前页面的方案及对比解析
前端
LFly_ice2 小时前
Next-4-路由导航
开发语言·前端·javascript
chilavert3182 小时前
技术演进中的开发沉思-267 Ajax:拖放功能
前端·javascript·ajax
守护砂之国泰裤辣2 小时前
el-select 选项偏移 到左边 左上角
前端·javascript·vue.js
明月_清风2 小时前
Chrome 插件开发科普:从零开始打造你的浏览器小工具
前端
若梦plus2 小时前
Node.js之TypeScript支持
前端·typescript
马优晨2 小时前
cssnano 在前端工程化中的应用
前端·cssnano应用·cssnano 是什么·cssnano介绍·css优化