当前位置: 首页 > news >正文

扬中网站制作公司/苏州seo安严博客

扬中网站制作公司,苏州seo安严博客,扬州外贸网站建设,网络舆情监测员1. Vue.js 基础介绍 1.1 什么是 Vue.js Vue.js(简称 Vue)是一个用于构建用户界面的渐进式 JavaScript 框架。与其他框架不同,Vue 被设计为可以逐步采用。Vue 的核心库只关注视图层,易于上手,便于与其他库或既有项目整合。 Vue 由尤雨溪(Evan You)在 2014 年创建。尤雨…

1. Vue.js 基础介绍

1.1 什么是 Vue.js

Vue.js(简称 Vue)是一个用于构建用户界面的渐进式 JavaScript 框架。与其他框架不同,Vue 被设计为可以逐步采用。Vue 的核心库只关注视图层,易于上手,便于与其他库或既有项目整合。

Vue 由尤雨溪(Evan You)在 2014 年创建。尤雨溪曾在 Google 工作,参与了 AngularJS 的开发,后来他希望提取 Angular 中他认为精华的部分,构建一个更轻量级的框架,于是创建了 Vue。

1.2 Vue.js 的特点

  1. 渐进式框架:可以逐步将 Vue 集成到项目中,无需一次全部采用。

  2. 响应式系统:Vue 提供了响应式且组件化的视图组件,当数据变化时,视图会自动更新。

  3. 虚拟 DOM:Vue 使用虚拟 DOM(Virtual DOM)技术提高渲染性能。

  4. 组件化开发:鼓励将应用拆分为独立可复用的组件,构建出大型应用。

  5. 轻量级:Vue 的体积小巧,压缩后仅约 20KB(Vue 2)或 10KB(Vue 3)。

  6. 易学易用:相较于其他前端框架,Vue 的学习曲线更平缓,API 设计简单直观。

  7. 丰富的工具链:Vue 提供了完整的开发工具链,如 Vue CLI、Vite、DevTools 等。

1.3 Vue.js 应用场景

Vue 可适用于多种场景:

  1. 单页应用(SPA):使用 Vue Router 构建单页应用,避免页面刷新提升用户体验。

  2. 多页应用:将 Vue 组件集成到传统的多页面应用中。

  3. 移动端应用:结合 Cordova、Capacitor 或 NativeScript 构建移动应用。

  4. 桌面应用:结合 Electron 构建桌面应用。

  5. 服务端渲染:使用 Nuxt.js 或手动配置 Vue SSR。

  6. 静态站点生成:使用 VuePress 或 Gridsome 生成静态站点。

1.4 Vue.js 版本历史

  • Vue 1.0:2015 年 10 月发布,奠定了 Vue 的基础架构。
  • Vue 2.0:2016 年 9 月发布,引入虚拟 DOM,提升性能。
  • Vue 2.6:2019 年 2 月发布,添加了 Composition API RFC 等特性。
  • Vue 3.0:2020 年 9 月发布,全新的架构,更好的性能和更小的体积。
  • Vue 3.2:2021 年 8 月发布,引入 <script setup> 语法。
  • Vue 3.3:2023 年 5 月发布,改进了 TypeScript 支持和宏性能。
  • Vue 3.4:2023 年 12 月发布,改进了渲染器和编译器性能。

2. Vue 2 与 Vue 3 比较

2.1 核心架构变化

特性Vue 2Vue 3
响应式系统Object.definePropertyProxy
代码组织Options API 为主Options API + Composition API
模板编译模板编译为渲染函数改进的模板编译策略,更好的静态提升
虚拟 DOM基本实现重写,更快的挂载和更新速度
TypeScript 支持有限支持完全支持,代码库用 TS 重写
Tree-Shaking有限支持全面支持,更小的打包体积

2.2 API 变化

Vue 3 新增的 API

  • Composition API(setup, ref, reactive 等)
  • Teleport 组件
  • Fragments(片段)
  • Suspense 组件
  • createApp 替代 new Vue()
  • 多个根节点支持
  • emits 选项

Vue 3 移除的 API

  • $on, $off, $once 事件 API
  • 过滤器(Filters)
  • $children 实例属性
  • $destroy 实例方法

2.3 性能对比

Vue 3 相比 Vue 2 在性能上有显著提升:

  1. 更小的包体积:Vue 3 核心库体积比 Vue 2 减小了约 41%,最小化和压缩后仅约 10KB。

  2. 更快的初始渲染:Vue 3 初始渲染速度比 Vue 2 快约 55%。

  3. 更高效的更新:由于优化的虚拟 DOM 和编译时提示,Vue 3 的更新性能比 Vue 2 快约 133%。

  4. 内存占用更低:Vue 3 减少了约 54% 的内存使用量。

2.4 生态系统适配

Vue 3 发布后,主要生态系统库逐步适配:

  • Vue Router:4.x 版本支持 Vue 3
  • Vuex:4.x 版本支持 Vue 3
  • Pinia:新一代状态管理库,专为 Vue 3 设计
  • Vite:新一代构建工具,原生支持 Vue 3
  • Nuxt:3.x 版本支持 Vue 3
  • UI 库:Element Plus、Vuetify 3、Quasar 2 等

2.5 迁移策略

从 Vue 2 迁移到 Vue 3 的建议策略:

  1. 渐进式迁移:使用 Vue 2.7(带有部分 Vue 3 特性)作为过渡。
  2. 使用迁移构建版本:Vue 3 提供了兼容 Vue 2 API 的构建版本。
  3. 使用迁移工具:Vue 团队提供了迁移助手工具。
  4. 分阶段迁移:先更新依赖,再更新代码风格,最后优化架构。
  5. 新项目直接使用 Vue 3:新项目建议直接采用 Vue 3。

3. 环境搭建与项目结构

3.1 安装 Vue

有多种方式可以在项目中使用 Vue:

3.1.1 直接引入

最简单的方法是通过 CDN 引入 Vue:

<!-- Vue 2 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script><!-- Vue 3 -->
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.37/dist/vue.global.js"></script>

对于生产环境,应使用压缩版本:

<!-- Vue 2 生产版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script><!-- Vue 3 生产版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.37"></script>
3.1.2 使用 npm

推荐使用 npm 管理依赖:

# Vue 2
npm install vue@2# Vue 3
npm install vue@next
3.1.3 使用 Vue CLI

Vue CLI 是一个官方的项目脚手架工具:

# 安装 Vue CLI
npm install -g @vue/cli# 创建一个新项目
vue create my-project# 选择 Vue 2 或 Vue 3 作为默认预设
3.1.4 使用 Vite

Vite 是一个新一代的前端构建工具,由 Vue 团队开发:

# 使用 npm
npm init vite@latest my-vue-app -- --template vue# 使用 yarn
yarn create vite my-vue-app --template vue# 使用 pnpm
pnpm create vite my-vue-app -- --template vue

3.2 项目结构

典型的 Vue 项目结构(基于 Vue CLI 或 Vite 创建):

my-vue-project/
├── .vscode/                # VSCode 配置
├── node_modules/           # npm 依赖
├── public/                 # 静态资源,不经过 webpack 处理
│   ├── favicon.ico         # 网站图标
│   └── index.html          # HTML 模板
├── src/                    # 源代码
│   ├── assets/             # 资源文件(会被打包)
│   ├── components/         # 组件
│   ├── router/             # 路由配置(Vue Router)
│   ├── store/              # 状态管理(Vuex/Pinia)
│   ├── views/              # 视图/页面组件
│   ├── App.vue             # 根组件
│   └── main.js             # 入口文件
├── .browserslistrc         # 浏览器兼容性配置
├── .eslintrc.js            # ESLint 配置
├── .gitignore              # Git 忽略文件
├── babel.config.js         # Babel 配置
├── package.json            # 项目配置和依赖
├── README.md               # 项目说明文档
└── vue.config.js           # Vue CLI 配置文件

Vite 项目结构略有不同,通常没有 vue.config.js,而是 vite.config.js

3.3 开发工具

有多种工具可帮助 Vue 开发:

3.3.1 Vue DevTools

Vue DevTools 是一个浏览器扩展,可以帮助调试 Vue 应用:

  • 检查组件树
  • 查看组件状态
  • 跟踪事件
  • 分析性能
  • 时间旅行调试(Vuex/Pinia)
3.3.2 IDE 支持

Visual Studio Code 是最受欢迎的 Vue 开发 IDE,推荐以下扩展:

  • Volar (Vue 3)
  • Vetur (Vue 2)
  • ESLint
  • Prettier
  • Vue VSCode Snippets
3.3.3 其他工具
  • Vue CLI GUI:Vue CLI 的图形界面
  • Vue Devtools Standalone:独立应用版 Vue Devtools
  • Vite:快速的开发服务器和构建工具
  • Nuxt DevTools:Nuxt.js 开发工具

3.4 配置文件

3.4.1 Vue CLI 配置

vue.config.js 文件可配置 Vue CLI 项目:

module.exports = {publicPath: process.env.NODE_ENV === 'production' ? '/my-app/' : '/',outputDir: 'dist',assetsDir: 'static',productionSourceMap: false,devServer: {port: 8080,proxy: {'/api': {target: 'http://localhost:3000',changeOrigin: true}}},css: {loaderOptions: {sass: {additionalData: `@import "@/styles/variables.scss";`}}}
}
3.4.2 Vite 配置

vite.config.js 文件配置 Vite 项目:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'export default defineConfig({plugins: [vue()],resolve: {alias: {'@': path.resolve(__dirname, './src')}},server: {port: 3000,proxy: {'/api': {target: 'http://localhost:8080',changeOrigin: true}}},build: {outDir: 'dist',assetsDir: 'assets',sourcemap: false}
})

4. Vue 核心概念

4.1 声明式渲染

Vue.js 的核心是声明式渲染系统,允许我们声明式地将数据渲染为 DOM:

<div id="app">{{ message }}
</div>
// Vue 2
new Vue({el: '#app',data: {message: 'Hello Vue!'}
})// Vue 3
Vue.createApp({data() {return {message: 'Hello Vue!'}}
}).mount('#app')

声明式渲染的优势:

  • 代码简洁易读
  • 关注数据而非 DOM 操作
  • 自动更新视图
  • 可维护性更高

4.2 响应式系统

Vue 的响应式系统使得数据与视图保持同步:

4.2.1 Vue 2 响应式原理

Vue 2 使用 Object.defineProperty 实现响应式:

let data = { message: 'Hello' }
let vm = {}Object.defineProperty(vm, 'message', {get() {return data.message},set(newValue) {data.message = newValueupdateView() // 更新视图}
})function updateView() {console.log('视图更新:', vm.message)
}// 修改属性触发视图更新
vm.message = 'Hello Vue!'

Vue 2 响应式系统限制:

  • 无法检测到对象属性的添加或删除
  • 无法检测数组索引的变化和长度的变化
  • 需要使用 Vue.set() 或 this.$set() 添加新属性
4.2.2 Vue 3 响应式原理

Vue 3 使用 Proxy 实现响应式:

let data = { message: 'Hello' }const handler = {get(target, key) {track(target, key) // 依赖跟踪return Reflect.get(target, key)},set(target, key, value) {const result = Reflect.set(target, key, value)trigger(target, key) // 触发更新return result}
}const proxy = new Proxy(data, handler)// 修改属性触发视图更新
proxy.message = 'Hello Vue 3!'
// 添加新属性也能触发视图更新
proxy.newProperty = 'New Value'

Vue 3 响应式系统优势:

  • 可以检测对象属性的添加和删除
  • 可以检测数组索引和长度的变化
  • 可以监听 Map, Set, WeakMap, WeakSet
  • 性能更好,消耗更少

4.3 指令系统

Vue 指令是带有 v- 前缀的特殊 HTML 属性,用于在模板中应用特殊的响应式行为:

4.3.1 常用内置指令
  • v-bind: 动态绑定属性
  • v-on: 绑定事件监听器
  • v-if: 条件性渲染元素
  • v-for: 基于数组渲染列表
  • v-model: 表单输入绑定
  • v-show: 切换元素的可见性
  • v-slot: 插槽内容分发
  • v-once: 一次性插值
  • v-pre: 跳过编译
  • v-cloak: 隐藏未编译的模板
  • v-text: 设置文本内容
  • v-html: 设置 HTML 内容
4.3.2 指令参数和修饰符

指令可以带参数和修饰符:

<!-- 参数 -->
<a v-bind:href="url">链接</a>
<button v-on:click="doSomething">点击</button><!-- 修饰符 -->
<form v-on:submit.prevent="onSubmit">表单</form>
<input v-model.trim="message">
4.3.3 自定义指令

可以注册自定义指令:

Vue 2:

// 全局注册
Vue.directive('focus', {inserted: function(el) {el.focus()}
})// 局部注册
new Vue({directives: {focus: {inserted: function(el) {el.focus()}}}
})

Vue 3:

// 全局注册
const app = Vue.createApp({})
app.directive('focus', {mounted(el) {el.focus()}
})// 局部注册
export default {directives: {focus: {mounted(el) {el.focus()}}}
}

自定义指令钩子函数:

Vue 2Vue 3描述
bindbeforeMount指令绑定到元素时调用
insertedmounted元素插入父节点时调用
update-元素更新时调用(去除)
componentUpdatedupdated组件和子组件更新时调用
unbindunmounted指令与元素解绑时调用

4.4 生命周期

Vue 组件有一系列的生命周期钩子,允许在特定阶段执行代码:

4.4.1 Vue 2 生命周期
new Vue({beforeCreate() {// 实例初始化后,数据观测和事件配置之前},created() {// 实例创建完成后调用,此时数据已经可用},beforeMount() {// 挂载开始之前被调用,render 函数首次调用},mounted() {// 实例挂载到 DOM 后调用,可访问 DOM 元素},beforeUpdate() {// 数据更改导致虚拟 DOM 重新渲染前调用},updated() {// 虚拟 DOM 重新渲染后调用},activated() {// keep-alive 组件激活时调用},deactivated() {// keep-alive 组件停用时调用},beforeDestroy() {// 实例销毁前调用},destroyed() {// 实例销毁后调用},errorCaptured() {// 捕获子孙组件错误时调用}
})
4.4.2 Vue 3 生命周期
export default {// 选项式 API 生命周期beforeCreate() { /* ... */ },created() { /* ... */ },beforeMount() { /* ... */ },mounted() { /* ... */ },beforeUpdate() { /* ... */ },updated() { /* ... */ },beforeUnmount() { /* ... */ }, // 替代 beforeDestroyunmounted() { /* ... */ },     // 替代 destroyedactivated() { /* ... */ },deactivated() { /* ... */ },errorCaptured() { /* ... */ },renderTracked() { /* ... */ },   // 新增:跟踪虚拟 DOM 重新渲染时调用renderTriggered() { /* ... */ }  // 新增:虚拟 DOM 重新渲染被触发时调用
}
4.4.3 Vue 3 组合式 API 生命周期钩子
import { onBeforeMount, onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted,onActivated,onDeactivated,onErrorCaptured,onRenderTracked,onRenderTriggered
} from 'vue'export default {setup() {// 注意:没有 beforeCreate 和 created 对应的钩子// setup 本身在 beforeCreate 之后、created 之前执行onBeforeMount(() => { /* ... */ })onMounted(() => { /* ... */ })onBeforeUpdate(() => { /* ... */ })onUpdated(() => { /* ... */ })onBeforeUnmount(() => { /* ... */ })onUnmounted(() => { /* ... */ })onActivated(() => { /* ... */ })onDeactivated(() => { /* ... */ })onErrorCaptured(() => { /* ... */ })onRenderTracked(() => { /* ... */ })onRenderTriggered(() => { /* ... */ })}
}

4.5 Vue 实例属性和方法

Vue 实例提供了许多有用的属性和方法:

4.5.1 Vue 2 实例属性和方法

实例属性

  • $data: Vue 实例监视的数据对象
  • $props: 当前组件接收的 props
  • $el: Vue 实例使用的根 DOM 元素
  • $options: 当前 Vue 实例的初始化选项
  • $parent: 父实例
  • $root: 根 Vue 实例
  • $children: 当前实例的直接子组件
  • $slots: 访问插槽内容
  • $scopedSlots: 访问作用域插槽
  • $refs: 持有注册过 ref 的所有 DOM 元素和组件实例
  • $isServer: 当前 Vue 实例是否运行于服务端
  • $attrs: 包含父作用域中非 prop 的属性绑定
  • $listeners: 包含父作用域中的事件监听器

实例方法

  • $watch(): 观察 Vue 实例变化的一个表达式或计算属性函数
  • $set(): 全局 Vue.set 的别名
  • $delete(): 全局 Vue.delete 的别名
  • $on(): 监听当前实例上的自定义事件
  • $once(): 监听一个自定义事件,但只触发一次
  • $off(): 移除自定义事件监听器
  • $emit(): 触发当前实例上的事件
  • $mount(): 手动挂载一个未挂载的实例
  • $forceUpdate(): 强制 Vue 实例重新渲染
  • $nextTick(): 将回调延迟到下次 DOM 更新循环之后执行
  • $destroy(): 完全销毁一个实例
4.5.2 Vue 3 实例属性和方法

Vue 3 移除了部分实例属性和方法,如 $on, $off, $once, $children 等。其余大部分属性保持不变,但获取方式可能不同:

// 选项式 API 中访问实例属性
export default {mounted() {console.log(this.$data)console.log(this.$el)}
}// 组合式 API 中访问实例属性
import { getCurrentInstance } from 'vue'export default {setup() {const instance = getCurrentInstance()// 在 setup 中访问实例(仅在开发环境可用)console.log(instance.data)console.log(instance.proxy.$el) // 需要通过 proxy 访问}
}

5. Vue 实例详解

5.1 创建 Vue 实例

5.1.1 Vue 2 创建实例

在 Vue 2 中,通过 new Vue() 创建实例:

const vm = new Vue({// 选项
})
5.1.2 Vue 3 创建应用

在 Vue 3 中,通过 createApp() 创建应用实例:

import { createApp } from 'vue'
import App from './App.vue'const app = createApp(App)
app.mount('#app')

Vue 3 的设计更加模块化,全局 API 移至应用实例:

// Vue 2
Vue.component('my-component', { /* ... */ })
Vue.directive('my-directive', { /* ... */ })
Vue.mixin({ /* ... */ })// Vue 3
const app = createApp(App)
app.component('my-component', { /* ... */ })
app.directive('my-directive', { /* ... */ })
app.mixin({ /* ... */ })

5.2 数据与方法

5.2.1 data 选项

Vue 实例的核心是 data 选项,它是一个对象或函数:

// Vue 2 根实例:对象语法
new Vue({data: {message: 'Hello'}
})// Vue 2 组件:函数语法
Vue.component('my-component', {data() {return {message: 'Hello'}}
})// Vue 3:始终使用函数语法
export default {data() {return {message: 'Hello'}}
}

为什么组件的 data 必须是函数? 为了确保每个组件实例有独立的数据副本,防止多个组件实例共享同一个数据对象。

5.2.2 methods 选项

methods 选项用于添加方法:

export default {data() {return {count: 0}},methods: {increment() {this.count++},decrement() {this.count--},reset() {this.count = 0}}
}

方法中的 this 自动绑定到 Vue 实例。

注意事项:

  • 不要使用箭头函数定义 method,因为箭头函数没有自己的 this
  • 方法可以在模板中直接调用,也可以用于事件处理

5.3 计算属性

计算属性是基于响应式依赖缓存的。只有相关依赖发生变化时才会重新计算:

export default {data() {return {firstName: 'John',lastName: 'Doe'}},computed: {// 基本用法fullName() {return this.firstName + ' ' + this.lastName},// 带 getter 和 setterfullNameWithSetter: {get() {return this.firstName + ' ' + this.lastName},set(newValue) {const names = newValue.split(' ')this.firstName = names[0]this.lastName = names[names.length - 1]}}}
}

计算属性的优势:

  • 缓存基于依赖,只有依赖变化时才重新计算
  • 声明式编程,更简洁易读
  • 自动跟踪依赖关系

5.4 侦听器

侦听器用于观察和响应 Vue 实例上的数据变动:

export default {data() {return {question: '',answer: 'Questions usually contain a question mark. ;-)'}},watch: {// 基本用法question(newQuestion, oldQuestion) {if (newQuestion.includes('?')) {this.getAnswer()}},// 深度侦听someObject: {handler(newValue, oldValue) {console.log('someObject changed')},deep: true},// 立即执行otherProperty: {handler(newValue, oldValue) {console.log('otherProperty changed')},immediate: true}},methods: {getAnswer() {this.answer = 'Thinking...'setTimeout(() => {this.answer = 'I think you should...'}, 1000)}}
}

侦听器特性:

  • 可以执行异步操作
  • 可以访问新值和旧值
  • 可以深度侦听对象变化
  • 可以在创建后立即执行

5.5 组件间通信

Vue 提供了多种组件通信方式:

5.5.1 Props 向下传递数据

父组件向子组件传递数据:

// 子组件
export default {props: {title: String,likes: Number,isPublished: Boolean,commentIds: Array,author: Object,callback: Function,contactsPromise: Promise}
}// 父组件
<blog-posttitle="My journey with Vue":likes="42":is-published="true"
></blog-post>
5.5.2 自定义事件向上传递数据

子组件向父组件传递数据:

// 子组件
export default {methods: {incrementCounter() {this.$emit('increment', 1)}}
}// 父组件
<button-counter @increment="incrementTotal"></button-counter>
5.5.3 其他通信方式
  • refs:直接访问子组件
  • provide/inject:祖先组件向所有子孙组件注入数据
  • EventBus:Vue 2 中创建一个事件总线(不推荐)
  • Vuex/Pinia:专门的状态管理解决方案
  • mitt/tiny-emitter:Vue 3 中的事件库替代 EventBus

6. 模板语法与渲染

6.1 插值

6.1.1 文本插值

使用双大括号语法插入文本:

<span>Message: {{ msg }}</span>
6.1.2 原始 HTML

使用 v-html 指令插入 HTML:

<div v-html="rawHtml"></div>

安全警告:使用 v-html 可能导致 XSS 攻击,只对可信内容使用,永不用于用户提供的内容。

6.1.3 属性绑定

使用 v-bind 指令绑定 HTML 属性:

<div v-bind:id="dynamicId"></div>
<!-- 简写 -->
<div :id="dynamicId"></div><!-- 布尔属性 -->
<button :disabled="isButtonDisabled">Button</button><!-- 多个属性绑定 -->
<div v-bind="{ id: 'container', class: 'wrapper' }"></div>

6.2 JavaScript 表达式

Vue 模板中支持完整的 JavaScript 表达式:

{{ number + 1 }}{{ ok ? 'YES' : 'NO' }}{{ message.split('').reverse().join('') }}<div :id="`list-${id}`"></div>

限制:每个绑定只能包含单个表达式,不支持语句或控制流。

6.3 指令详解

指令是带有 v- 前缀的特殊 attribute,指令的值是单个 JavaScript 表达式。

6.3.1 参数

指令可以接收参数,在指令名之后以冒号表示:

<a v-bind:href="url">链接</a>
<button v-on:click="doSomething">点击</button>
6.3.2 动态参数

可以用方括号括起来的 JavaScript 表达式作为指令的参数:

<a v-bind:[attributeName]="url">链接</a>
<button v-on:[eventName]="doSomething">点击</button>
6.3.3 修饰符

修饰符是以点开头的特殊后缀,表示指令应该以特殊方式绑定:

<!-- 阻止默认行为 -->
<form v-on:submit.prevent="onSubmit"></form><!-- 键盘事件 -->
<input v-on:keyup.enter="submit"><!-- 表单修饰符 -->
<input v-model.trim="msg">

6.4 缩写

Vue 为最常用的指令提供了缩写:

<!-- 完整语法 -->
<a v-bind:href="url">链接</a>
<button v-on:click="doSomething">点击</button><!-- 缩写 -->
<a :href="url">链接</a>
<button @click="doSomething">点击</button><!-- 动态参数缩写 -->
<a :[key]="url">链接</a>
<button @[event]="doSomething">点击</button>

6.5 模板中的条件与循环

6.5.1 条件渲染

使用 v-if, v-else-if, v-else 进行条件渲染:

<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else>Not A/B/C</div>

使用 v-show 控制元素显示:

<h1 v-show="ok">Hello!</h1>

v-ifv-show 对比:

  • v-if 是"真正"的条件渲染,元素会被销毁和重建
  • v-show 只是切换 CSS display 属性
  • v-if 有更高的切换开销,v-show 有更高的初始渲染开销
  • 频繁切换使用 v-show,条件很少改变使用 v-if
6.5.2 列表渲染

使用 v-for 基于数组渲染列表:

<ul><li v-for="(item, index) in items" :key="item.id">{{ index }} - {{ item.text }}</li>
</ul>

v-for 也可以遍历对象属性:

<ul><li v-for="(value, key, index) in object" :key="key">{{ index }}. {{ key }}: {{ value }}</li>
</ul>

v-forv-if 不应在同一元素上使用,因为 v-forv-if 优先级更高。

6.6 过滤器 (Vue 2)

Vue 2 支持过滤器,可用于文本格式化:

<!-- 在双花括号中 -->
{{ message | capitalize }}<!-- 在 v-bind 中 -->
<div v-bind:id="rawId | formatId"></div>
filters: {capitalize(value) {if (!value) return ''value = value.toString()return value.charAt(0).toUpperCase() + value.slice(1)}
}

注意:Vue 3 已移除过滤器,推荐使用方法或计算属性代替。

7. 计算属性与侦听器

7.1 计算属性详解

计算属性是基于其响应式依赖进行缓存的。

7.1.1 基本用法
export default {data() {return {message: 'Hello'}},computed: {// 计算属性的 getterreversedMessage() {// `this` 指向组件实例return this.message.split('').reverse().join('')}}
}
7.1.2 计算属性缓存 vs 方法

计算属性和方法的区别:

  • 计算属性基于依赖缓存,依赖不变时不会重新计算
  • 方法在每次重新渲染时都会执行
  • 对于计算开销大的操作,应优先使用计算属性
// 计算属性(有缓存)
computed: {expensiveOperation() {console.log('Computing expensive operation')return this.items.filter(item => item.important).map(...)}
}// 方法(无缓存)
methods: {expensiveMethod() {console.log('Running expensive method')return this.items.filter(item => item.important).map(...)}
}
7.1.3 计算属性的 setter

计算属性默认只有 getter,但也可以提供 setter:

export default {data() {return {firstName: 'John',lastName: 'Doe'}},computed: {fullName: {// getterget() {return this.firstName + ' ' + this.lastName},// setterset(newValue) {const names = newValue.split(' ')this.firstName = names[0]this.lastName = names[names.length - 1] || ''}}}
}

使用 setter:

// 此时会调用 setter: this.firstName 和 this.lastName 会相应更新
this.fullName = 'Jane Smith'

7.2 侦听器详解

侦听器适用于需要在数据变化时执行异步或开销较大的操作。

7.2.1 基本用法
export default {data() {return {question: '',answer: 'Questions usually contain a question mark. ;-)'}},watch: {// 每当 question 发生变化时,该函数将会执行question(newQuestion, oldQuestion) {if (newQuestion.includes('?')) {this.getAnswer()}}},methods: {getAnswer() {this.answer = 'Thinking...'axios.get('https://api.example.com/answer').then(response => {this.answer = response.data.answer}).catch(error => {this.answer = 'Error! Could not reach the API. ' + error})}}
}
7.2.2 深度侦听

默认情况下,侦听器只会监听顶层属性的变化。使用 deep 选项进行深度侦听:

export default {data() {return {user: {name: 'John',profile: {age: 30,address: {city: 'New York'}}}}},watch: {user: {handler(newValue, oldValue) {console.log('User object changed')},deep: true},// 也可以直接监听嵌套属性'user.profile.age'(newValue, oldValue) {console.log('Age changed from', oldValue, 'to', newValue)}}
}
7.2.3 立即执行

使用 immediate 选项可以使侦听器在创建时立即执行:

watch: {question: {handler(newQuestion, oldQuestion) {this.answer = 'Waiting for you to stop typing...'this.debouncedGetAnswer()},immediate: true}
}
7.2.4 停止侦听

在选项式 API 中,侦听器会在组件销毁时自动停止。如果需要提前停止,可以使用 $watch 返回的取消函数:

const unwatch = this.$watch('question', (newQuestion) => {// ...
})// 当不再需要观察时,调用取消函数
unwatch()

在组合式 API 中,watch 函数返回停止侦听的函数:

import { ref, watch } from 'vue'export default {setup() {const question = ref('')// 开始侦听const stopWatching = watch(question, (newQuestion) => {// ...})// 停止侦听stopWatching()}
}

7.3 计算属性 vs 侦听器

计算属性和侦听器的选择原则:

  • 计算属性:适用于根据现有数据派生出新数据

    • 更加声明式
    • 有缓存机制
    • 适合同步计算
  • 侦听器:适用于响应数据变化

    • 支持异步操作
    • 可以执行副作用(如修改 DOM、发送网络请求)
    • 可以访问变化前后的值
    • 可以监视多个数据源
7.3.1 何时使用计算属性
// 使用计算属性(更好)
computed: {fullName() {return this.firstName + ' ' + this.lastName}
}// 使用侦听器(不推荐)
watch: {firstName(newVal) {this.fullName = newVal + ' ' + this.lastName},lastName(newVal) {this.fullName = this.firstName + ' ' + newVal}
}
7.3.2 何时使用侦听器
// 使用侦听器
watch: {searchQuery(newQuery) {this.isLoading = truethis.debouncedGetResults(newQuery)}
},
methods: {// 防抖函数debounce(fn, delay) {let timeoutreturn function(...args) {clearTimeout(timeout)timeout = setTimeout(() => fn.apply(this, args), delay)}},created() {this.debouncedGetResults = this.debounce(this.getResults, 300)},getResults(query) {axios.get('/api/search', { params: { query } }).then(response => {this.results = response.datathis.isLoading = false})}
}

8. Class 与 Style 绑定

8.1 绑定 HTML Class

8.1.1 对象语法
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
data() {return {isActive: true,hasError: false}
}

渲染结果:

<div class="active"></div>

也可以绑定一个对象:

<div :class="classObject"></div>
data() {return {classObject: {active: true,'text-danger': false}}
}

或使用计算属性:

computed: {classObject() {return {active: this.isActive && !this.error,'text-danger': this.error && this.error.type === 'fatal'}}
}
8.1.2 数组语法
<div :class="[activeClass, errorClass]"></div>
data() {return {activeClass: 'active',errorClass: 'text-danger'}
}

渲染结果:

<div class="active text-danger"></div>

数组中使用条件:

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

更简洁的方式是在数组中使用对象语法:

<div :class="[{ active: isActive }, errorClass]"></div>
8.1.3 与组件结合使用

当在自定义组件上使用 class 时,这些类将被添加到组件的根元素上:

<!-- 假设这是父组件模板 -->
<my-component class="baz"></my-component>
// 组件定义
Vue.component('my-component', {template: '<p class="foo bar">Hi</p>'
})

渲染结果:

<p class="foo bar baz">Hi</p>

8.2 绑定内联样式

8.2.1 对象语法
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data() {return {activeColor: 'red',fontSize: 30}
}

通常绑定一个样式对象会更清晰:

<div :style="styleObject"></div>
data() {return {styleObject: {color: 'red',fontSize: '13px'}}
}
8.2.2 数组语法

可以将多个样式对象应用到同一个元素上:

<div :style="[baseStyles, overridingStyles]"></div>
data() {return {baseStyles: {color: 'blue',fontSize: '16px'},overridingStyles: {fontWeight: 'bold',border: '1px solid black'}}
}
8.2.3 自动前缀

使用 :style 时,Vue 会自动为需要添加浏览器前缀的 CSS 属性添加适当的前缀:

<div :style="{ display: 'flex' }"></div>

渲染结果(取决于浏览器):

<div style="display: -webkit-flex; display: flex;"></div>
8.2.4 多重值

从 Vue 2.3 开始,可以为样式属性提供一个包含多个值的数组,只会渲染数组中浏览器支持的最后一个值:

<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

渲染结果(在支持 flex 的浏览器中):

<div style="display: flex;"></div>

9. 条件渲染

9.1 v-if 指令

v-if 指令用于条件性地渲染一块内容,只有当表达式为 truthy 时,内容才会被渲染:

<h1 v-if="awesome">Vue is awesome!</h1>

9.2 v-else 和 v-else-if

v-elsev-else-if 必须紧跟在 v-ifv-else-if 元素之后:

<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else>Not A/B/C</div>

9.3 在 <template> 上使用 v-if

对于需要同时条件渲染多个元素,可以使用不可见的 <template> 元素包裹,最终渲染结果将不包含 <template> 元素:

<template v-if="ok"><h1>Title</h1><p>Paragraph 1</p><p>Paragraph 2</p>
</template>

9.4 v-show 指令

v-show 也用于条件性显示元素,但元素始终会被渲染并保留在 DOM 中,只是简单地切换 CSS 的 display 属性:

<h1 v-show="ok">Hello!</h1>

注意v-show 不支持在 <template> 元素上使用,也不支持 v-else

9.5 v-if vs v-show

  • v-if

    • "真正"的条件渲染(创建和销毁元素)
    • 有更高的切换开销
    • 在运行时条件很少改变时使用
    • 支持 <template>v-elsev-else-if
  • v-show

    • 元素始终被渲染,只是切换 CSS display 属性
    • 有更高的初始渲染开销
    • 需要频繁切换时使用
    • 不支持 <template>v-else

9.6 v-if 与 v-for 一起使用

不推荐同时使用 v-ifv-for:当它们同时存在于一个元素上时,v-for 的优先级高于 v-if

下面的代码,v-if 将分别重复运行于每个 v-for 循环中:

<!-- 不推荐 -->
<ul><li v-for="user in users" v-if="user.active" :key="user.id">{{ user.name }}</li>
</ul>

两个建议的替代方案:

  1. 使用计算属性过滤:
<!-- 推荐 -->
<ul><li v-for="user in activeUsers" :key="user.id">{{ user.name }}</li>
</ul>
computed: {activeUsers() {return this.users.filter(user => user.active)}
}
  1. 使用 <template>v-forv-if 移到外层:
<!-- 推荐 -->
<ul><template v-for="user in users" :key="user.id"><li v-if="user.active">{{ user.name }}</li></template>
</ul>

10. 列表渲染

10.1 v-for 基础用法

10.1.1 遍历数组

使用 v-for 指令基于一个数组来渲染一个列表:

<ul><li v-for="item in items" :key="item.id">{{ item.text }}</li>
</ul>

也可以访问当前项的索引:

<ul><li v-for="(item, index) in items" :key="item.id">{{ index }} - {{ item.text }}</li>
</ul>
10.1.2 遍历对象

可以用 v-for 遍历对象的属性:

<ul><li v-for="value in object" :key="value">{{ value }}</li>
</ul>

可以提供第二个参数为键名:

<ul><li v-for="(value, key) in object" :key="key">{{ key }}: {{ value }}</li>
</ul>

还可以提供第三个参数为索引:

<ul><li v-for="(value, key, index) in object" :key="key">{{ index }}. {{ key }}: {{ value }}</li>
</ul>
10.1.3 遍历数字范围

v-for 也可以接受整数,会重复对应次数:

<div><span v-for="n in 10" :key="n">{{ n }} </span>
</div>

注意这里的 n 是从 1 开始,而不是从 0 开始。

10.2 维护状态与 key

Vue 默认使用"就地更新"的策略,如果数据项的顺序被改变,Vue 不会移动 DOM 元素来匹配数据项的顺序,而是更新每个元素。

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每项提供一个唯一的 key 属性:

<div v-for="item in items" :key="item.id"><!-- 内容 -->
</div>

key 的最佳实践

  • 使用唯一标识符(如 id)作为 key
  • 不要使用索引作为 key(除非列表是静态的且不会重新排序)
  • 尽量不要使用随机值作为 key,这会导致性能低下

10.3 数组更新检测

10.3.1 变更方法

Vue 能够检测响应式数组的变更方法,这些方法会触发视图更新:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

示例:

// 这些方法会触发视图更新
this.items.push({ id: 4, text: 'New Item' })
this.items.pop()
10.3.2 替换数组

有些方法不会改变原始数组,而是返回一个新数组,例如:

  • filter()
  • concat()
  • slice()

当使用这些方法时,可以用新数组替换旧数组:

// 替换整个数组(Vue 能够检测)
this.items = this.items.filter(item => item.text.match(/Foo/))
10.3.3 注意事项

由于 JavaScript 的限制,Vue 不能检测到数组的以下变动:

  1. 利用索引直接设置一个数组项:

    // 这不会触发视图更新(Vue 2)
    this.items[index] = newValue
    
  2. 修改数组的长度:

    // 这不会触发视图更新(Vue 2)
    this.items.length = newLength
    

解决方案(Vue 2):

// 使用 Vue.set
Vue.set(this.items, index, newValue)
// 或
this.$set(this.items, index, newValue)// 使用 splice
this.items.splice(index, 1, newValue)// 修改长度
this.items.splice(newLength)

在 Vue 3 中,使用 Proxy 解决了这些问题,直接修改索引或长度会触发更新。

10.4 显示过滤/排序后的结果

显示一个数组的过滤或排序副本,而不实际改变原始数据:

<ul><li v-for="n in evenNumbers" :key="n">{{ n }}</li>
</ul>
data() {return {numbers: [1, 2, 3, 4, 5]}
},
computed: {evenNumbers() {return this.numbers.filter(n => n % 2 === 0)}
}

对于复杂的情况,也可以使用方法:

<ul><li v-for="n in even(numbers)" :key="n">{{ n }}</li>
</ul>
data() {return {numbers: [1, 2, 3, 4, 5]}
},
methods: {even(numbe
http://www.whsansanxincailiao.cn/news/31979442.html

相关文章:

  • 物流公司网站建设/seo如何优化网站步骤
  • 网站站点断开/搜索量查询百度指数
  • wordpress博客页修改/seo网站权重
  • 网站建设电话销售话术/数据分析师35岁以后怎么办
  • 临沂高端网站建设/网站建设与网页设计制作
  • 网站做链接操作步骤/郴州网站建设推广公司
  • 中山网站搭建/百度公司
  • 重庆潼南网站建设报价/吉林seo推广
  • 桂市做网站的朋友/新媒体推广渠道有哪些
  • 开发商交房需要提供哪些证书/百度seo排名查询
  • wordpress 手册/福州seo公司
  • 那个网站做室内比较好的/长春seo外包
  • 长安网站建设多少钱/seo品牌优化整站优化
  • 网站建设及维护价钱/线上营销策略
  • 怎么做网站流量统计分析/如何自己创建网站
  • p2c网站方案/福州seo快速排名软件
  • 做外贸网站卖什么东西好/淮南网站seo
  • 怎样用java做网站/郑州网站优化
  • 好的网站布局/媒体营销
  • 学校门户网站/网站的建设流程
  • 网站开发国外研究现状/搜索引擎营销的特点是
  • 宁波网站建设企业网站制作/教育培训机构网站
  • 校园网站建设与管理问题分析/如何进行网站性能优化
  • 建设 展示型企业网站/互联网推广是干什么的
  • windous 系统 做网站/离我最近的电脑培训中心
  • 南京建网站/培训心得体会
  • 什么网站可以做简历/百度推广关键词怎么设置好
  • 网站中英文切换怎麼做/滕州百度推广
  • 三门峡网站制作/自己怎么做网站优化
  • 怎样用代码做网站/广告服务平台