更新元素的文本内容,v-text
通过设置元素的 textContent
属性来工作,因此它将覆盖元素中所有现有的内容。
<span v-text="msg"></span>
<!-- 等同于 -->
<span>{{msg}}</span>
v-html
<div v-html="htmlContent"></div>
Vue实例的数据属性htmlContent
包含HTML字符串,比如"<p>Hello World!</p>"
,那么v-html就会使这个div
元素将会渲染出一个段落,包含文本"Hello World!",v-html
会强行覆盖子元素。
注意事项
-
安全性:由于
v-html
会解析字符串为HTML,因此如果这个字符串包含用户输入的内容,那么可能会有跨站脚本(XSS)攻击的风险。确保你信任你的数据源,或者使用其他方式来清理和转义HTML内容。 -
性能:频繁地使用
v-html
可能会导致性能问题,因为它涉及到DOM的频繁操作。如果你需要频繁更新HTML内容,考虑使用其他方式来优化性能。 -
响应性:与
v-bind
或v-model
不同,v-html
不会对数据的每个变化都重新渲染HTML。如果数据对象的结构发生变化,可能需要使用其他方法来确保视图的响应性。 -
使用场景:
v-html
适用于需要动态渲染HTML内容的场景,例如动态加载的富文本编辑器内容、用户生成的内容等。
v-show
基于表达式值的真假性,来改变元素的可见性。
v-show
通过设置内联样式的 display
CSS 属性来工作,当元素可见时将使用初始 display
值。
当条件改变时,也会触发过渡效果。
因为v-show
避免了DOM的创建和销毁,所以它在条件频繁变化时性能更好
<div v-show="isShow">该元素由v-show控制是否展示</div>
v-if
v-if
是一个条件性渲染指令,它根据条件的真值来决定是否渲染元素。
当条件变化时,v-if
会触发真实的DOM插入或删除操作。如果条件由false
变为true
,Vue会创建元素并插入到DOM中;如果条件由true
变为false
,Vue会销毁元素并从DOM中移除。
<div v-if="isShow">该元素由v-if控制是否渲染</div>
v-else
, v
-else-if 这两者与 v-if
连用,效果等同于if - else 结构
v-on
v-on
是Vue.js中的一个指令,用于监听DOM事件并在事件发生时执行一些JavaScript代码。它是Vue
响应式系统的一部分,允许开发者将事件处理逻辑绑定到Vue实例的数据上。
例如:绑定点击事件
<button v-on:click="method()">触发点击事件</button>
<!-- 简写为 @ 某一事件件即可 -->
<button @click="method()">触发点击事件</button>
v-on
无法直接绑定JavaScript中的函数,需要把JavaScript中的函数作为Vue
实例中的一部分(data,methods)后才能进行调用
v-on
自带一个默认的event
参数,通过它可以获取事件对象的属性和方法:
-
event.target
:触发事件的元素。 -
event.currentTarget
:事件绑定的元素,即当前组件的根元素。 -
event.type
:事件类型,如'click'
、'mouseover'
等。 -
event.preventDefault()
:阻止事件的默认行为。 -
event.stopPropagation()
:阻止事件继续传播到父元素。
v-bind
用于动态地绑定一个或多个属性,它可以用来响应式地更新HTML元素的属性。
绑定属性
imageSrc
和 imageAlt
是Vue
实例的数据属性
<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 使用对象语法同时绑定多个属性 -->
<img v-bind="{ src: imageSrc, alt: imageAlt }">
<!-- 使用简写 -->
<img :src="imageSrc" :alt="imageAlt">
绑定布尔属性
v-bind
可以非常智能地处理它们的真值和假值。如果表达式的值为假(例如:null
、undefined
、false
、0
或空字符串''
),布尔属性将不会被渲染。
<!-- 布尔属性 -->
<button v-bind:disabled="isButtonDisabled">Click me</button>
设置CSS类
active
类将根据 isActive
的值动态添加或移除,text-danger
类将根据 hasError
的值动态添加或移除。
<div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
绑定内联样式
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
对象与数组语法
v-bind
的对象语法允许你传递一个对象,对象的属性将被转换为DOM元素的属性。
new Vue({
data: {
buttonAttributes: {
type: 'button',
disabled: true,
title: 'Click me'
}
}
})
<button v-bind="buttonAttributes">Button</button>
v-bind
的数组语法允许你传递一个数组,数组中的每个元素都将成为元素的一个属性。
<button v-bind:[attributeName]="attributeValue">Button</button>
简写
v-bind
有一个简写形式,使用:
代替v-bind
v-for
用于基于源数据列表重复渲染一个元素或模板多次。它是Vue
响应式系统的一部分,能够确保当源数据变化时,DOM也会相应地更新。
<span v-for="(item,index) in items" :key="index" :style="{margin: '4px'}">{{ item }}</span>
items
是Vue实例的一个数组数据属性。v-for
指令将为数组中的每个元素渲染一个li
元素。每个li
都将显示对应数组元素的text
属性。:key
是一个唯一键值,用于帮助Vue
跟踪每个节点的身份,从而重用和重新排序现有元素。
遍历对象
<ul>
<li v-for="(value, key, index) in object" :key="key">
{{ index }}. {{ key }}: {{ value }}
</li>
</ul>
范围循环
<div v-for="n in 10" :key="n">{{ n }}</div>
-
使用
key
属性:当使用v-for
时,应该尽可能地为每个元素提供一个唯一的key
属性。这有助于Vue
识别哪些元素是被改变、添加或移除的,从而提高渲染效率。 -
避免在
v-for
中使用异步操作:在v-for
处理的数据上执行异步操作可能会导致不可预见的结果。 -
不要在
v-for
中使用v-if
:每个v-for
元素都应该是独立的,不应该与v-if
结合使用。如果需要根据条件渲染列表项,应该使用计算属性来过滤列表。 -
性能考虑:虽然
v-for
非常强大,但渲染大量列表可能会对性能产生影响。在这种情况下,考虑使用虚拟滚动或其他优化技术。 -
响应性:确保
v-for
绑定的数据是响应式的。Vue
无法检测以下更改:-
直接通过索引设置一个项:
items[index] = newValue
-
修改数组的长度:
items.length = newLength
对于数组的更改,应该使用响应式的方法,如:
Vue.set(items, index, newValue)
或更改数组的方法,如:items.push(newItem)
。 -
key 属性的必要性
使用key
的影响:
-
提高性能:
key
帮助Vue
识别哪些元素是被改变、添加或移除的。当列表数据变化时,Vue
可以使用key
来决定是否需要重新渲染元素,或者是否可以通过复用现有元素来提高性能。没有key
时,Vue
可能会执行不必要的DOM
操作,导致性能下降。 -
避免组件状态丢失:当列表项的顺序变化或项目被重新排序时,如果使用
key
,Vue
能够通过key
来跟踪每个节点的身份,确保组件或元素的状态(例如,输入框的内容)得以保持。 -
确保正确的DOM更新:
key
确保Vue
可以精确地定位到需要更新的DOM元素,避免出现渲染错误。 -
提高可预测性:使用
key
可以提高列表渲染的可预测性,尤其是在动态内容变化时。
不使用key
的影响:
-
性能问题:没有
key
时,Vue
在更新列表时会采用更通用的方法,这可能导致不必要的DOM操作,从而影响性能。 -
组件状态丢失:在列表顺序变化时,组件的状态可能会丢失,因为
Vue
可能无法正确地识别哪些元素是被移动的,而不是被替换的。 -
渲染错误:在某些情况下,没有
key
可能导致渲染错误,比如在删除或插入列表项时,可能会导致其他项的显示错误。 -
列表项闪烁:在某些动画或过渡效果中,没有
key
可能导致列表项在更新时出现闪烁现象。
何时使用key
:
-
当列表项的顺序可能会变化时。
-
当列表项可能被动态添加或删除时。
-
当列表项中包含组件,并且组件状态需要保持时。
何时可以不使用key
:
-
当列表项的顺序和数量在渲染后不会发生变化时。
-
当列表项非常简单,不包含任何状态或组件时。
v-model
用于在表单输入和应用状态之间创建双向数据绑定。它是一个语法糖
,相当于同时绑定了 v-bind
和 v-on
指令。
<input v-model="message" placeholder="输入一些文本">
<!-- 等价 -->
<input :value="message" @input="handleInput">
<!--
handleInput(event) {
console.log(event.target)
this.message = event.target.value;
}
-->
v-model 在 以下表单元素中同样起作用
多行文本
<textarea v-model="message" placeholder="多行文本输入"></textarea>
单选框、复选框
<!-- 单选按钮 gender的值根据选择结果,在男、女之间切换-->
<input type="radio" id="male" value="male" v-model="gender">
<label for="male">男</label>
<input type="radio" id="female" value="female" v-model="gender">
<label for="female">女</label>
<!-- 复选框 hobbies 是一个数组,每个被选择的元素都会被添加到 hobbies 中-->
<input type="checkbox" id="likes Football" value="Football" v-model="hobbies">
<label for="likes Football">足球</label>
<input type="checkbox" id="likes Basketball" value="Basketball" v-model="hobbies">
<label for="likes Basketball">篮球</label>
下拉框
<!-- 与单选框情况类似,没有选择是为空字符串'' 或 默认值(设置了的话)-->
<select v-model="selectedCity">
<option value="New York">纽约</option>
<option value="San Francisco">旧金山</option>
<option value="Los Angeles">洛杉矶</option>
</select>
用于渲染元素和组件时只执行一次。当使用v-once
时,Vue
会确保在该元素或组件上的数据变化不会触发重新渲染。这意味着一旦初始渲染完成,该元素或组件就不会再更新。
v-once
通常用在以下场景:
-
性能优化:如果你有一个静态的元素或组件,但因为父组件的更新而频繁重新渲染,使用
v-once
可以避免这种不必要的渲染。 -
复杂元素:对于包含大量静态内容的复杂元素,使用
v-once
可以提高性能。 -
一次性操作:在某些情况下,你可能只需要执行一次初始化操作,之后不再需要更新,这时可以使用
v-once
。
v-slot
slot
是一种用于组件内容分发的 API,允许子组件在模板中预留一个或多个位置,这些位置可以被组件的使用者填充自定义的内容。这使得组件设计更加灵活和可复用
-
默认插槽
<FancyButton>
Click me! <!-- 插槽内容 -->
</FancyButton>
<button class="fancy-btn">
<slot></slot> <!-- 插槽出口 -->
</button>
Click me 会替换掉 slot
标签 就像 下面代码所写的那样,插槽可以设置默认值,<slot>默认值</slot>
,当父组件没有给子组件传入数值的时候默认值才会起到作用,插槽可以访问到父组件的数据,当你使用 插值表达式{{message}}
时可以进行动态的渲染子组件
<button class="fancy-btn">
Click me!
</button>
-
具名插槽
当我们需要用到多个插槽时,就需要对插槽进行区别,于是命名是一件很有必要的事情,对于这种场景,<slot>
元素可以有一个特殊的 attribute name
,用来给各个插槽分配唯一的 ID,以确定每一处要渲染的内容
<!-- -->
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
要为具名插槽传入内容,我们需要使用一个含 v-slot
指令的 <template>
元素,并将目标插槽的名字传给该指令
<BaseLayout>
<template v-slot:header>
<!-- header 插槽的内容放这里 -->
</template>
</BaseLayout>
插槽的命名可以是动态的
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
<!-- 缩写为 -->
<template #[dynamicSlotName]>
...
</template>
</base-layout>
v-slot
有对应的简写 #
,因此 <template v-slot:header>
可以简写为 <template #header>
。
<BaseLayout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<template #default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template #footer>
<p>Here's some contact info</p>
</template>
</BaseLayout>
最终渲染出的 子元素HTML结构 如下
<div class="container">
<header>
<h1>Here might be a page title</h1>
</header>
<main>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</main>
<footer>
<p>Here's some contact info</p>
</footer>
</div>
-
条件插槽
有时你需要根据插槽是否存在来渲染某些内容。你可以结合使用 v-slot
属性与 v-if
来实现。
就像这样
<template>
<div class="card">
<div v-if="$slots.header" class="card-header">
<slot name="header" />
</div>
<div v-if="$slots.default" class="card-content">
<slot />
</div>
<div v-if="$slots.footer" class="card-footer">
<slot name="footer" />
</div>
</div>
</template>
当 header、footer 或 default 存在时,我们希望包装它们以提供额外的样式
-
作用域插槽
在某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点,我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽。
可以像对组件传递 props 那样,向一个插槽的出口上传递 attributes:
<!-- <MyComponent> 的模板 -->
<div>
<slot :text="greetingMessage" :count="1"></slot>
</div>
通过子组件标签上的 v-slot
指令,直接接收到了一个插槽 props 对象:
<MyComponent v-slot="slotProps">
{{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
v-slot="slotProps"
可以类比这里的函数签名,和函数的参数类似,我们也可以在 v-slot
中使用解构:
<MyComponent v-slot="{ text, count }">
{{ text }} {{ count }}
</MyComponent>
自定义指令
自定义指令允许你直接对元素进行低层次操作,包括但不限于DOM事件监听、动态属性绑定、样式应用等。
directives: {
highlight: {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
}
}
<input v-highlight>
自定义指令可以提供以下几个钩子函数:
-
bind
:只调用一次,指令第一次绑定到元素时调用,用以设置一次性的状态。 -
inserted
:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。 -
update
:所在组件的VNode
更新时调用,但是可能发生在其子组件的VNode
更新之前,指令的值可能发生了变化,也可能没有。 -
componentUpdated
:指令所在组件的VNode
及其子组件的VNode
全部更新后调用。 -
unbind
:只调用一次,指令与元素解绑时调用。
注意事项
-
自定义指令应该尽可能保持简洁,避免进行复杂的操作。
-
自定义指令应该具有良好的封装性,不应该依赖于Vue实例的外部状态。
-
自定义指令不应该修改应用的状态,它们应该只影响绑定的元素。
修饰符
修饰符(Modifiers)是特殊的后缀,用于对指令的行为进行约束
.stop
阻止事件继续传播到父元素
<button @click.stop="doSomething">Stop Event Propagation</button>
.prevent
组织事件的默认行为
<form @submit.prevent="submitForm">Submit without reloading</form>
.capture
事件捕获模式。事件从捕获阶段开始触发,然后到达目标元素
<div @click.capture="doSomething">Capture Event</div>
.self
只有当事件是从元素本身触发时才触发回调,而不是从子元素触发
<div @click.self="handleClick">Click on this div</div>
.once
事件将只触发一次,之后被移除
<button @click.once="doThisOnce">Do this once</button>
passive
告诉浏览器你不想阻止事件的默认行为,通常与scroll
事件结合使用以提高性能
<div @scroll.passive="handleScroll">Passive event listener</div>
.sync
用于创建一个同步的prop
,允许子组件更新父组件的绑定值
<child-component :value.sync="parentValue"></child-component>
.camel
自动将短横线命名的属性转换为驼峰命名
<input :aria-label="label"> <!-- 转换为 "ariaLabel" -->
.number
尽可能把输入的字符串转化为数字
<input v-model.number="age" type="number">
.trim
过滤首尾输入的空格
<input v-model.trim="message">