Fork me on GitHub

Vue3-内置内容

内置指令

<template>
  <div>

    <!-- v-text -->
    <h2 v-text="title"></h2>

    <!-- v-html -->
    <div v-html="htmlContent"></div>

    <!-- v-show -->
    <p v-show="showText">这段文字用 v-show 控制显示</p>

    <!-- v-if / v-else-if / v-else -->
    <div v-if="status === 'success'">操作成功</div>
    <div v-else-if="status === 'error'">操作失败</div>
    <div v-else>未知状态</div>

    <!-- v-for -->
    <ul>
      <li v-for="(item, index) in list" :key="index">{{ index + 1 }} - {{ item }}</li>
    </ul>

    <!-- v-on -->
    <button @click="handleClick">点击我</button>

    <!-- v-bind -->
    <img :src="imgUrl" :alt="imgAlt" />

    <!-- v-model -->
    <input v-model="inputText" placeholder="双向绑定输入框" />
    <p>你输入了: {{ inputText }}</p>

    <!-- v-slot -->
    <BaseCard>
      <template #header>
        <h3>我是插槽 header</h3>
      </template>
      <template #default>
        <p>我是默认插槽内容</p>
      </template>
      <template #footer>
        <p>我是 footer 插槽</p>
      </template>
    </BaseCard>

    <!-- v-pre -->
    <div v-pre>{{ 不会被 Vue 解析的内容 }}</div>

    <!-- v-once -->
    <p v-once>只渲染一次,数据变化也不会更新:{{ onceText }}</p>

    <!-- v-memo (仅 Vue3.2+,性能优化,演示写法) -->
    <p v-memo="[memoCondition]">v-memo 控制的内容</p>

    <!-- v-cloak -->
    <p v-cloak>v-cloak 避免闪烁(需结合 CSS)</p>

  </div>
</template>

<script setup>
import { ref } from 'vue'
import BaseCard from './BaseCard.vue'

const title = ref('这是 v-text 渲染的标题')
const htmlContent = ref('<strong style="color:red">这是 v-html 渲染的加粗内容</strong>')
const showText = ref(true)
const status = ref('success') // 可改为 'error' 或其他值测试
const list = ref(['苹果', '香蕉', '橘子'])
const imgUrl = ref('https://via.placeholder.com/100')
const imgAlt = ref('示例图片')
const inputText = ref('')
const onceText = ref('这是只渲染一次的内容')
const memoCondition = ref(true)
</script>

<style scoped>
[v-cloak] {
  display: none;
}
</style>

BaseCard 组件

<template>
  <div class="card">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

<script setup>
</script>

<style scoped>
.card {
  border: 1px solid #ddd;
  padding: 10px;
  margin-top: 10px;
  border-radius: 8px;
}
</style>
指令 作用说明
v-text 替换元素的文本内容,类似 textContent
v-html 渲染 HTML 字符串,注意 XSS 安全风险
v-show 控制元素显示隐藏,实际操作的是 display 样式。
v-if 条件渲染,元素是否存在于 DOM 中。
v-else-if 条件分支,配合 v-if 使用。
v-else 条件分支兜底方案。
v-for 列表循环渲染,支持数组、对象、数字。
v-on@ 绑定事件监听,常用于按钮、输入框交互。
v-bind: 动态绑定属性或 prop,控制值。
v-model 双向数据绑定,常用于表单控件。
v-slot 具名插槽,父组件向子组件传递结构化内容。
v-pre 跳过该元素和子节点的 Vue 编译,输出原始模板内容。
v-once 只渲染一次,数据变化不再更新该部分,适合静态结构。
v-memo 性能优化,绑定条件不变时不重新渲染(Vue3.2+ 新特性)。
v-cloak 页面加载期间防止模板闪烁,需配合 CSS [v-cloak]{ display: none; }

区别

  • v-showv-if 区别:

    特性 v-show v-if
    操作原理 控制 display 样式 控制 DOM 节点是否存在
    性能消耗 初次渲染开销小,切换快 每次切换都会销毁与重建 DOM
    适用场景 频繁切换 条件不频繁变化的结构
  • v-html 警告:
    渲染 HTML 字符串时,若数据不可信,存在 XSS 攻击风险,必须严格过滤或避免。

内置组件

1. 过渡动画

<template>
  <button @click="show = !show">切换</button>
  
  <Transition name="fade">
    <p v-if="show">这是带淡入淡出效果的内容</p>
  </Transition>
</template>

<script setup>
import { ref } from 'vue'

const show = ref(true)
</script>

<style scoped>
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>

2. 列表过渡

<template>
  <button @click="add">添加</button>

  <TransitionGroup name="list" tag="ul">
    <li v-for="item in items" :key="item">{{ item }}</li>
  </TransitionGroup>
</template>

<script setup>
import { ref } from 'vue'

const items = ref(['苹果', '香蕉', '橘子'])

const add = () => {
  items.value.push('新增' + Math.floor(Math.random() * 100))
}
</script>

<style scoped>
.list-enter-active, .list-leave-active {
  transition: all 0.5s;
}
.list-enter-from {
  opacity: 0;
  transform: translateY(-20px);
}
.list-leave-to {
  opacity: 0;
  transform: translateY(20px);
}
</style>

3. 缓存组件状态

<template>
  <button @click="tab = 'A'">组件 A</button>
  <button @click="tab = 'B'">组件 B</button>

  <KeepAlive>
    <component :is="tab === 'A' ? CompA : CompB" />
  </KeepAlive>
</template>

<script setup>
import { ref } from 'vue'
import CompA from './CompA.vue'
import CompB from './CompB.vue'

const tab = ref('A')
</script>

CompA.vue、CompB.vue 随便写,切换时组件不会被销毁,状态会被保留。

4. 传送 DOM 到其他位置

<template>
  <button @click="show = !show">打开弹窗</button>

  <Teleport to="body">
    <div v-if="show" class="modal">
      这是传送到 body 的弹窗
      <button @click="show = false">关闭</button>
    </div>
  </Teleport>
</template>

<script setup>
import { ref } from 'vue'

const show = ref(false)
</script>

<style scoped>
.modal {
  position: fixed;
  top: 30%;
  left: 40%;
  background: #fff;
  padding: 20px;
  border: 1px solid #ddd;
  box-shadow: 0 0 10px rgba(0,0,0,0.3);
}
</style>

5. 异步组件占位

<template>
  <Suspense>
    <template #default>
      <AsyncComp />
    </template>
    <template #fallback>
      <p>加载中...</p>
    </template>
  </Suspense>
</template>

<script setup>
import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
  new Promise(resolve => {
    setTimeout(() => {
      resolve(import('./HelloWorld.vue'))
    }, 2000)
  })
)
</script>
组件 作用描述
<Transition> 单个元素或组件的进入、离开过渡动画。
<TransitionGroup> 列表元素的批量进入、离开动画,支持同时多个元素。
<KeepAlive> 缓存组件状态,切换时不销毁,常用于标签页、路由缓存。
<Teleport> 将子元素传送到 DOM 的其他位置,常用于弹窗、全局挂载。
<Suspense> 处理异步组件加载,提供加载中的占位符。

特殊元素

1. 动态组件

<template>
  <button @click="current = 'CompA'">切换到组件 A</button>
  <button @click="current = 'CompB'">切换到组件 B</button>

  <component :is="current" />
</template>

<script setup>
import { ref } from 'vue'
import CompA from './CompA.vue'
import CompB from './CompB.vue'

const current = ref('CompA')
</script>

2. 插槽传递

//父组件
<template>
  <BaseCard>
    <template #header>
      <h3>我是头部内容</h3>
    </template>
    <template #default>
      <p>这是默认插槽内容</p>
    </template>
    <template #footer>
      <p>我是底部内容</p>
    </template>
  </BaseCard>
</template>

<script setup>
import BaseCard from './BaseCard.vue'
</script>


//子组件 BaseCard.vue
<template>
  <div class="card">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

3. template结构辅助

<template>
  <ul>
    <template v-for="(item, index) in list" :key="index">
      <li>{{ item }}</li>
      <li class="desc">描述:{{ item }}的附加信息</li>
    </template>
  </ul>
</template>

<script setup>
import { ref } from 'vue'

const list = ref(['苹果', '香蕉', '橘子'])
</script>

image

特殊 Attributes

1. key

key 保证每个元素的唯一标识,Vue 能高效复用 DOM 节点,避免重复渲染。

<template>
  <button @click="shuffle">打乱列表</button>
  <ul>
    <li v-for="item in list" :key="item.id">{{ item.name }}</li>
  </ul>
</template>

<script setup>
import { ref } from 'vue'

const list = ref([
  { id: 1, name: '苹果' },
  { id: 2, name: '香蕉' },
  { id: 3, name: '橘子' }
])

const shuffle = () => {
  list.value.sort(() => Math.random() - 0.5)
}
</script>

2. ref

•ref 用于获取真实 DOM 节点或子组件实例。
•.value 访问 DOM 对象,操作原生方法。

<template>
  //Vue 会自动把这个 input 的真实 DOM 节点,赋值给 inputRef.value。
  <input ref="inputRef" placeholder="点击按钮自动聚焦" />
  <button @click="focusInput">聚焦输入框</button>
</template>

<script setup>
import { ref } from 'vue'

// 定义容器,初始值是 null
const inputRef = ref(null)

const focusInput = () => {
  inputRef.value.focus()    //通过 .value 访问真实 DOM,调用 focus 方法
}
</script>

3. is

动态指定渲染的组件或元素

<template>
  <button @click="currentTag = 'h1'">切换为 h1</button>
  <button @click="currentTag = 'p'">切换为段落</button>
  <button @click="currentTag = 'MyComp'">切换为自定义组件</button>
  //currentTag的值是h1,所以这里会用h1渲染
  <component :is="currentTag">
    这里是动态渲染的内容
  </component>
</template>

<script setup>
import { ref } from 'vue'
import MyComp from './MyComp.vue'
//定义currentTag的值,可以是h1、可以是p也可以是子组件
const currentTag = ref('h1')
</script>

image

posted @ 2025-07-05 21:26  秋夜雨巷  阅读(14)  评论(0)    收藏  举报