Vue的基础使用

目录

补充小知识:

MVVM和MVC区别与联系

什么是响应式数据

js当中操作数组的相关函数

防抖和节流:

防抖的写法:

节流的写法:

一、标签属性

1.v-html属性:

2.v-show和v-if区别与联系

3.v-else:v-else-if:

4.v-on:事件名=“内联语句”

v-on:事件名=“methods内部函数”

5. v-bind

 6.v-for

7.v-model

二、

1.指令修饰符:

事件修饰符(v-on 或 @)​ 

 表单修饰符(v-model)

 键盘事件修饰符(@keydown / @keyup)​

鼠标修饰符(@click 等)​ 

2.计算属性

3.watch的使用


补充小知识:

样式的使用

对比项CSSLESS
本质原生样式语言,直接由浏览器解析。CSS 预处理器,需编译为 CSS 后生效。
变量支持原生变量(通过 --var: value 和 var(--var))。支持更灵活的变量(如 @color: #333;),可跨文件复用。
嵌套原生 CSS 需逐层编写选择器,代码冗余。支持嵌套语法,层级关系更清晰(类似 HTML 结构)。
混合(Mixins)​无混合功能,需重复编写相同代码。支持混合(复用代码块),可带参数,类似函数。
运算支持基础计算(如 calc(100% - 20px))。支持复杂运算(如颜色运算、变量计算),直接在预处理阶段完成。
函数依赖原生 CSS 函数(如 rgb()hsl())。提供内置函数(如颜色处理、数学计算),可自定义函数。
场景推荐技术原因
简单静态页面CSS无需复杂功能,直接使用原生 CSS 更轻量。
大型项目或团队协作LESS变量、嵌套和混合提升开发效率和可维护性。
动态样式需求LESS运算、循环和函数支持复杂逻辑。
兼容旧项目CSS避免引入编译步骤,减少迁移成本。
现代 CSS 特性足够CSS若原生 CSS 变量和 calc() 等已满足需求,无需预处理器。

 &:hover可以替代重新写一遍名称,&就指代当前对象

.link {
  color: #333;
  &:hover {
    color: #007bff;
  }
  &::after {
    content: "→";
  }
}

MVVM和MVC区别与联系

现在所学的vue就是mvc架构

对比项MVC (Model-View-Controller)MVVM (Model-View-ViewModel)联系
核心角色Model​(数据)、View​(UI)、Controller​(逻辑)Model​(数据)、View​(UI)、ViewModel​(绑定层)均遵循分层设计,分离关注点,提升可维护性。
交互流程用户操作 → ​View → ​Controller → 更新 ​Model → 刷新 ​View用户操作 → ​View → ​ViewModel → 自动同步 ​Model → 更新 ​View均通过中间层(Controller/ViewModel)协调 ​Model 和 ​View 的交互。
数据绑定无自动数据绑定,需手动更新视图(如操作 DOM)。双向数据绑定​(如 Vue、Angular),自动同步视图与数据。均依赖 ​Model 作为数据源,但 MVVM 通过绑定减少手动操作。
职责划分Controller 处理业务逻辑和用户输入,直接控制视图更新。ViewModel 封装视图逻辑和数据绑定,不直接操作 DOM。中间层(Controller/ViewModel)均负责逻辑处理,但实现方式不同。
视图更新View 可能直接监听 ​Model 变化(如观察者模式)。ViewModel 通过绑定机制自动触发视图更新。目标均为保持 ​View 与 ​Model 的一致性。
适用场景传统服务端渲染应用(如 Spring MVC、Rails)。数据驱动的现代前端应用(如 Vue、React、Angular)。均适用于构建分层架构的应用程序。
代码耦合度View 与 ​Model 可能直接交互,耦合度较高。View 与 ​Model 完全解耦,通过 ​ViewModel 通信。均致力于降低耦合,但 MVVM 解耦更彻底。
典型框架ASP.NET MVC、Spring MVC、Ruby on Rails。Vue.js、Angular、Knockout.js。

什么是响应式数据

响应式数据是指当数据发生变化时,系统能够自动更新依赖该数据的视图或逻辑,而无需开发者手动操作。这种机制通过数据绑定技术,实现了数据驱动视图的自动同步。例如,当你在前端框架中修改一个变量时,页面中用到该变量的地方会自动刷新,无需手动更新 DOM。

 ref和reactive

特性​**ref**​**reactive**
适用类型基本类型(stringnumberboolean)或对象/数组的引用。对象或数组(直接处理复杂数据结构)。
响应式包装方式将值包装为 { value: ... } 的响应式对象,需通过 .value 访问。直接创建对象的响应式代理,属性可直接访问。
模板自动解包在模板中直接使用变量名,无需 .value属性直接访问,无需解包。
解构响应性解构时会保留响应性(每个属性独立为 ref)。直接解构会丢失响应性,需用 toRefs 转换。
TS 类型支持通过泛型明确类型(如 ref<string>(''))。自动推断类型,但需确保对象结构明确。
重新赋值允许直接替换整个值(ref.value = newValue)。不能直接替换整个对象,需修改属性(或使用 Object.assign)。
性能开销略高(需包装为对象)。略低(直接代理原对象)。
场景推荐使用原因
基本类型数据ref更简洁,避免手动包装对象。
复杂对象/数组reactive直接操作属性,无需 .value,代码更直观。

js当中操作数组的相关函数

方法/函数作用是否修改原数组返回值Vue 响应式支持示例
​**push()**在数组末尾添加元素(可多个)。新数组长度(number支持(自动触发更新)arr.push('a', 'b'); → arr = [原元素, 'a', 'b']
​**pop()**删除数组最后一个元素被删除的元素支持(自动触发更新)arr.pop() → 返回最后一个元素,数组长度减 1。
​**shift()**删除数组第一个元素被删除的元素支持(自动触发更新)arr.shift() → 返回第一个元素,数组长度减 1。
​**unshift()**在数组开头添加元素(可多个)。新数组长度(number支持(自动触发更新)arr.unshift('a', 'b'); → arr = ['a', 'b', 原元素...]
​**splice()**删除/替换/插入元素(指定位置)。被删除的元素数组支持(自动触发更新)arr.splice(1, 2, 'x', 'y') → 从索引 1 删除 2 个元素,插入 'x' 和 'y'。
​**sort()**对数组元素排序(默认按字符串 Unicode 编码)。排序后的原数组支持(自动触发更新)arr.sort((a, b) => a - b); → 升序排列。
​**reverse()**反转数组顺序。反转后的原数组支持(自动触发更新)arr.reverse() → [3, 2, 1](原数组 [1, 2, 3]
​**slice()**返回数组的浅拷贝片段(start 到 end-1)。新数组片段需重新赋值触发更新(如 arr = newArrarr.slice(1, 3) → 返回索引 1 到 2 的元素,原数组不变。
​**concat()**合并多个数组或值,返回新数组。合并后的新数组需重新赋值触发更新arr.concat([4, 5]) → 合并原数组和 [4, 5]
​**join()**将数组元素连接为字符串(默认用逗号分隔)。连接后的字符串无(不涉及数组修改)[1, 2].join('-') → "1-2"
​**indexOf()**返回元素首次出现的索引(无则返回 -1)。索引值或 -1无(仅查询)arr.indexOf('a') → 返回 'a' 的索引。
​**includes()**判断数组是否包含某元素(支持简单数据类型)。true / false无(仅查询)arr.includes('a') → 是否包含 'a'。
​**find()**返回第一个满足条件的元素(无则返回 undefined)。元素或 undefined无(仅查询)arr.find(item => item > 2) → 第一个大于 2 的元素。
​**findIndex()**返回第一个满足条件的元素索引(无则返回 -1)。索引或 -1无(仅查询)arr.findIndex(item => item > 2) → 第一个大于 2 的索引。
​**filter()**返回满足条件的所有元素组成的新数组。新数组需重新赋值触发更新arr.filter(item => item > 2) → 所有大于 2 的元素。
​**map()**对每个元素执行函数,返回新数组。新数组需重新赋值触发更新arr.map(item => item * 2) → 每个元素乘以 2。
​**forEach()**对每个元素执行函数(无返回值)。undefined无(遍历操作)arr.forEach(item => console.log(item)) → 打印每个元素。
​**reduce()**从左到右累加处理数组元素,返回最终结果。累加结果无(计算操作)arr.reduce((acc, item) => acc + item, 0) → 数组求和。
​**some()**判断数组中是否有元素满足条件(至少一个)。true / false无(检测操作)arr.some(item => item > 2) → 是否有元素大于 2。
​**every()**判断数组所有元素是否都满足条件。true / false无(检测操作)arr.every(item => item > 2) → 是否所有元素都大于 2。
​**flat()**将嵌套数组“拉平”成一维数组(默认拉平一层)。新数组需重新赋值触发更新[1, [2, [3]]].flat(2) → [1, 2, 3]
​**flatMap()**先对元素执行 map,再对结果执行 flat(深度 1)。新数组需重新赋值触发更新[1, 2].flatMap(x => [x, x*2]) → [1, 2, 2, 4]

防抖和节流:

特性节流 (Throttle)防抖 (Debounce)
触发频率固定时间间隔执行一次事件停止后延迟执行
适用场景高频持续触发高频但只需最后结果
典型应用滚动事件、窗口调整、鼠标移动搜索建议、输入验证
执行时机首次可立即执行只执行最后一次
防抖的写法:

逻辑是,当被触发时,首先清除生词的定时器,然后再重新设置定时器,定时器的原理是,收到请求后,隔一段时间再去执行内部包裹的函数逻辑,间隔的时间为wait,单位是毫秒,这样就可以实现,当连续多次点击时,不停的重新刷新计时器,只执行最后一次的点击。 

// 清除之前的定时器
    clearTimeout(timeoutId);
    
    // 设置新的定时器
    timeoutId = setTimeout(() => {
      func.apply(context, args);
    }, wait);
节流的写法:
<template>
  <button @click="throttledSubmit">提交订单</button>
</template>

<script setup>
import { throttle } from 'lodash-es'

const throttledSubmit = throttle(() => {
  console.log('订单提交')
}, 1000, { leading: true, trailing: false })
</script>

一、标签属性

1.v-html属性:

相当于js当中innerHTML,实现数据绑定

2.v-show和v-if区别与联系

对比项v-ifv-show
渲染机制条件为 false 时,元素不会渲染到 DOM​(完全销毁组件/元素)。条件为 false 时,元素通过 display: none ​隐藏,但始终存在于 DOM 中。
切换开销切换时涉及组件的销毁和重新创建​(高切换开销)。仅切换 CSS 的 display 属性(低切换开销)。
初始渲染开销初始条件为 false 时,无渲染开销(节省初始资源)。无论初始条件如何,元素都会渲染(可能有更高的初始渲染开销)。
作用范围支持在 <template> 标签上使用。不支持在 <template> 标签上使用。
生命周期切换时会触发组件的生命周期钩子(如 createdmounteddestroyed)。切换时不会触发组件的生命周期钩子(仅 CSS 变化)。
与 v-else 配合可搭配 v-else 或 v-else-if 实现分支逻辑。不可搭配 v-else 使用。
使用场景适合不频繁切换或需要减少初始负载的场景(如权限控制、动态表单)。适合频繁切换显示状态的场景(如选项卡、折叠菜单)。

v-if:登陆后就不用渲染了,不需要频繁切换

v-show:

频繁切换显示和隐藏

3.v-else:v-else-if:

指令作用
v-else表示 v-if 的“否则”分支,​无需条件表达式
v-else-if表示 v-if 的额外条件分支,​需要条件表达式

v-else**:

  • 必须紧跟在 v-if 或 v-else-if 的元素之后。
  • 没有条件表达式,直接绑定到最近的 v-if/v-else-if
<div v-if="isAdmin">管理员内容</div>
<div v-else>普通用户内容</div>

v-else-if**:

  • 必须紧跟在 v-if 或另一个 v-else-if 的元素之后。
  • 必须提供条件表达式。
<div v-if="score >= 90">优秀</div>
<div v-else-if="score >= 80">良好</div>
<div v-else-if="score >= 60">及格</div>
<div v-else>不及格</div>

4.v-on:事件名=“内联语句”

v-on:事件名=“methods内部函数”

v-on:的缩写为@

事件名:

鼠标事件click点击事件
dblclick双击事件
mouseover/mouseout鼠标移入/移出元素
mousedown/mouseup鼠标按下/释放
键盘事件keydown键盘按下时触发
keyup键盘释放时触发
keypress按下字符键时触发(已废弃,建议用 keydown
表单事件submit表单提交事件
input输入框内容变化时触发
change表单元素值变化时触发(如选择框、文件上传)
焦点事件focus元素获得焦点
blur元素失去焦点
其他事件scroll元素滚动时触发
resize窗口大小改变时触发
自定义事件自定义事件名组件通过 $emit 触发的自定义事件(如 custom-event

 内联语句的实现

<!-- 直接修改数据 -->
<button @click="count += 1">点击增加:{{ count }}</button>

<!-- 调用方法并传参 -->
<button @click="showMessage('Hello')">显示消息</button>

<!-- 访问事件对象 $event -->
<input @keyup.enter="submitForm($event)">

<!-- 多语句用分号分隔 -->
<button @click="count += 1; logCount()">增加并记录</button>

methods内部函数的实现:

可以进行传参

<button @click="handleDelete(item.id)">删除</button>
methods: {
  handleDelete(id) {
    this.items = this.items.filter(item => item.id !== id);
  }
}

5. v-bind

v-bind 用于动态绑定 HTML 属性或组件 Prop 到 Vue 实例的数据,实现数据驱动视图更新。引入v-bind的主要原因在于在属性标签之中无法使用插值表达式,所以无法用插值表达式绑定定义的变量值,而应该使用v-bind,使用v-bind后将全局查找是否存在绑定值。

语法说明
v-bind:属性名="表达式"完整写法,动态绑定属性。
:属性名="表达式"简写形式(推荐)。
v-bind="对象"批量绑定多个属性(传入一个对象)。

(1):

动态绑定 HTML 属性 

<!-- 动态链接 -->
<a :href="url">访问网站</a>

<!-- 动态图片路径 -->
<img :src="imagePath">

<!-- 动态禁用按钮 -->
<button :disabled="isButtonDisabled">提交</button>

动态绑定 Class

对象语法:根据布尔值切换类名

<div :class="{ active: isActive, 'text-danger': hasError }"></div>
 

<button v-for="(item,index) in btns" :key="index" @click="changeMag" :class="{button:true,borderLeft:index===0}">{{item}}</button>
//为index==0的标签多赋值一个类名

数组语法:应用多个类名。

<div :class="[activeClass, errorClass]"></div>

 内联样式:实现对单个样式的动态调整,冒号后面必须是字符串

<template>
  <div :style="{ color: textColor, fontSize: fontSize + 'px' }">
    动态样式文本
  </div>
</template>

 6.v-for

v-for 用于基于数据源(数组/对象)循环渲染元素或组件。

语法说明
v-for="(item, index) in items"遍历数组,item 是元素,index 是索引(可选)。
v-for="(value, key, index) in object"遍历对象,value 是值,key 是键名(可选),index 是索引(可选)。
v-for="n in 10"遍历数字范围(从 1 到 10)。
<template>
  <ul>
    <li v-for="(fruit, index) in fruits" :key="index">
      {{ index + 1 }}. {{ fruit }}
    </li>
  </ul>
</template>

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

关键属性绑定 :key

  • 必须为每项绑定唯一标识​(如 id),避免渲染错误和性能问题。
  • 错误示例:key="index"(索引不稳定,可能导致数据错乱)。
  • 正确示例
    <div v-for="item in items" :key="item.id">{{ item.name }}</div>

 通过绑定key,可以实现当删除或其他操作时,可以精准让内核知道要给那个对象添加或删除,否则的话,只会进行复用

7.v-model

v-model 是 Vue 提供的双向数据绑定指令,主要用于表单元素和自定义组件,简化 v-bind 和 v-on 的组合使用。

场景示例说明
表单输入绑定<input v-model="text">快速实现表单数据与状态同步。
自定义组件双向绑定<CustomComponent v-model="data" />父子组件间数据双向传递。
复杂表单控件<select v-model="selected"><option>A</option></select>下拉框、复选框组等复杂交互控件。

元素类型用法示例绑定数据类型注意事项
普通文本框<input type="text" v-model="textValue">字符串(String支持 .trim 修饰符自动去除首尾空格:v-model.trim="textValue"
单选框(单选)​html<input type="radio" value="A" v-model="radioValue"><input type="radio" value="B" v-model="radioValue">字符串/数值(与 value 一致)多个单选框必须绑定同一 v-model,且每个设置不同 value
复选框(单个)​<input type="checkbox" v-model="isChecked">布尔值(Boolean选中时为 true,未选中为 false
复选框(多选)​html<input type="checkbox" value="A" v-model="checkboxValues"><input type="checkbox" value="B" v-model="checkboxValues">数组(Array必须绑定到数组,且每个复选框设置不同 value
下拉菜单(单选)​html<select v-model="selectedOption"> <option value="A">选项A</option> <option value="B">选项B</option></select>字符串/数值(与 value 一致)默认选中第一个 <option>,可设置 <option disabled> 作为占位符。
下拉菜单(多选)​<select v-model="selectedOptions" multiple>数组(Array需添加 multiple 属性,按住 Ctrl/Cmd 多选。
文本域<textarea v-model="message"></textarea>字符串(String不支持 value 属性,始终用 v-model 绑定。

二、

1.指令修饰符:

事件修饰符(v-on 或 @)​ 

修饰符作用示例等价操作
.stop阻止事件冒泡@click.stop="handler"event.stopPropagation()
.prevent阻止默认行为@submit.prevent="handler"event.preventDefault()
.capture使用事件捕获模式(从外到内触发)@click.capture="handler"-
.self仅当事件由元素自身触发(非子元素)时执行@click.self="handler"if (event.target === element)
.once事件只触发一次@click.once="handler"自动解绑事件
.passive提示浏览器不阻止默认行为(常用于滚动优化)@scroll.passive="handler"-
串联多个修饰符可串联使用@click.stop.prevent

 表单修饰符(v-model

修饰符作用示例说明
.lazy将 input 事件改为 change 事件(延迟更新)v-model.lazy="text"输入框失焦后同步数据
.number自动将输入值转为数字类型v-model.number="age"输入 "25" → 25(数值类型)
.trim自动去除首尾空格v-model.trim="username"输入 " Alice " → "Alice"

 键盘事件修饰符(@keydown / @keyup)​

修饰符作用示例支持的按键
按键别名监听特定按键@keyup.enter="submit".enter.tab.esc.space 等
系统修饰键组合按键触发@keyup.ctrl.enter="save".ctrl.alt.shift.meta
.exact精确匹配系统键组合@keyup.ctrl.exact="handler"仅当只按 ctrl 时触发

鼠标修饰符(@click 等)​ 

修饰符作用示例支持的按键
.left左键点击@click.left="handler"-
.right右键点击@click.right="handler"-
.middle中键点击@click.middle="handler"-

2.计算属性

计算属性(Computed Properties)​ 是一种声明式的数据派生方式,用于根据现有响应式数据动态生成新值,并自动缓存结果。它的核心特点是 ​高效、简洁、可维护,尤其适合处理模板中需要复杂逻辑的表达式。说人话就是对现有数据进行计算,并返回响应式结果,该响应式结果会根据所利用到运算的数的变化影响的计算结果的变化而变化。在计算属性内部可直接通过this.属性名访问外部定义的属性。

本质上计算属性就是一个方法,但是使用该方法时,直接当成属性来用

 computed: {
          totalScore() {
            return this.list.reduce((sum, item) => sum + item.score, 0)
          },
          averageScore () {
            if (this.list.length === 0) {
              return 0
            }
            return (this.totalScore / this.list.length).toFixed(2)
          }
        }
 <td colspan="5">
                <span>总分:{{ totalScore }}</span>
                <span style="margin-left: 50px">平均分:{{ averageScore }}</span>
              </td>

计算属性对比直接定义一个function函数计算结果的区别在于:

对比项​**computed 计算属性**​**methods 方法**
定义方式在 Vue 实例的 computed 选项中声明为函数,返回一个值。在 Vue 实例的 methods 选项中声明为函数,可执行任意操作。
缓存机制有缓存,依赖数据未变化时直接返回缓存结果。无缓存,每次调用都重新执行函数。
依赖追踪自动追踪响应式依赖(如 data 中的属性)。不自动追踪依赖,需手动处理逻辑。
参数支持不接受参数​(默认只有 getter,需参数时可返回函数)。可接受参数,灵活处理动态数据。
使用场景适合派生数据(如过滤列表、格式化数据)。适合事件处理、异步操作或需要主动触发的逻辑。
模板调用方式作为属性使用,​无需括号{{ fullName }}作为方法调用,​需括号​(即使无参数):{{ formatDate() }}
性能优化高频访问时性能更优(依赖不变时复用结果)。高频调用可能导致重复计算。
Setter 支持支持定义 get 和 set(默认只有 getter)。无 setter 概念,直接通过方法修改数据。

 以下是计算属性的全写,set和get方法。当在输入框中输入名字时,就为fullname进行了赋值,即调用了fullname的set方法,姓和名就可以被拆分出来

<template>
  <div>
    <!-- 输入框绑定计算属性 fullName -->
    <input v-model="fullName" placeholder="请输入全名">
    <p>姓氏:{{ firstName }}</p>
    <p>名字:{{ lastName }}</p>
    <p>全名:{{ fullName }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      firstName: "张",
      lastName: "三"
    };
  },
  computed: {
    // 计算属性 fullName,定义 get 和 set
    fullName: {
      // 获取全名(拼接 firstName 和 lastName)
      get() {
        return `${this.lastName}${this.firstName}`; // "张三"
      },
      // 设置全名(拆分并更新 firstName 和 lastName)
      set(newFullName) {
        // 假设格式为 "姓氏名字",如 "李四"
        const names = newFullName.split("");
        if (names.length >= 2) {
          this.lastName = names[0];  // 姓氏(第一个字符)
          this.firstName = names.slice(1).join(""); // 名字(剩余字符)
        }
      }
    }
  }
};
</script>

3.watch的使用

检测单个值

import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newVal, oldVal) => {
  console.log(`数值变化: ${oldVal} → ${newVal}`)
})

 深度监测

检测对象内部嵌套的属性时,需要开启深度检测

const complexData = reactive({
  nested: {
    items: [1, 2, 3]
  }
})

watch(
  complexData,
  (newVal) => {
    console.log('深层变化:', newVal.nested.items)
  },
  { deep: true } // 必须开启深度监听
)

立即执行

const searchQuery = ref('')

watch(
  searchQuery,
  async (newQuery, oldQuery, onCleanup) => {
    const controller = new AbortController()
    onCleanup(() => controller.abort()) // 清理副作用
    
    const results = await fetch(`/search?q=${newQuery}`, {
      signal: controller.signal
    })
    console.log('搜索结果:', results)
  },
  { immediate: true } // 组件创建时立即执行
)

watch和watcheffect区别

特性​**watch**​**watchEffect**
监听目标显式指定监听的数据源(需传入 source)。自动追踪回调内的所有响应式依赖。
初始执行需配置 immediate: true 以立即执行。默认立即执行。
旧值获取提供 newVal 和 oldVal不提供旧值。
适用场景需要精准控制监听的数据或旧值。依赖多个数据且无需旧值的场景(如日志记录)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值