vue - 基础
创建 vue 项目
创建vue3
npm create vue@latest
✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add an End-to-End Testing Solution? … No / Cypress / Nightwatch / Playwright
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
✔ Add Vue DevTools 7 extension for debugging? (experimental) … No / Yes
Scaffolding project in ./<your-project-name>...
Done.
创建vue2
安装vue-cli
npm install -g @vue/cli
创建
vue create vue2_lifecycle

VS CODE 插件
Vue (Official)
Vue VSCode Snippets
vue 常用包
unplugin-auto-import:自动导入API,从此告别“import地狱”
# npm
npm i -D unplugin-auto-import unplugin-vue-components
# yarn
yarn add -D unplugin-auto-import unplugin-vue-components
# pnpm
pnpm add -D unplugin-auto-import unplugin-vue-components
vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
AutoImport({
imports: ['vue', 'vue-router', 'pinia'],
dts: 'src/auto-imports.d.ts',
dirs: ['src/composables', 'src/hooks'],
// 解决ESLint报错
eslintrc: {
enabled: true,
filepath: './.eslintrc-auto-import.json',
},
}),
// 自动导入组件
Components({
dirs: ['src/components', 'src/views/components'], // 多组件目录
resolvers: [
ElementPlusResolver(), // Element Plus组件自动导入
],
dts: 'src/components.d.ts',
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
})imports: 预设名称或自定义导入映射
dts: - 指定用于生成相应.d.ts 文件的文件路径。
- 当在本地安装了typescript时,此选项默认启用。
- 设为false可禁用此功能。
dirs: 要自动导入的目录路径
eslintrc: 生成相应的.eslintrc-auto-import.json 文件。
如果
eslint.config.js 添加 './.eslintrc-auto-import.json',
import { defineConfig, globalIgnores } from 'eslint/config'
import globals from 'globals'
import js from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
const autoImportGlobals = require('./.eslintrc-auto-import.json')
export default defineConfig([
{
name: 'app/files-to-lint',
files: ['**/*.{js,mjs,jsx,vue}'],
},
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
{
languageOptions: {
globals: {
...globals.browser,
...autoImportGlobals.globals,
},
},
},
js.configs.recommended,
...pluginVue.configs['flat/essential'],
skipFormatting,
])tsconfig.json 配置
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Node"
},
"include": [
"src/**/*",
"src/auto-imports.d.ts",
"src/components.d.ts"
]
}
-
避免过度自动导入:
- 对于核心 API / 组件(如 Vue 的 ref、Element Plus 的 ElButton)可自动导入;
- 对于低频使用的 API / 组件,建议手动导入,提升代码可读性。
-
处理 ESLint 报错:
- unplugin-auto-import 需开启
eslintrc.enabled,并在.eslintrc中引入生成的配置; - unplugin-vue-components 一般无需额外配置 ESLint,因为模板中的组件不会被 ESLint 检查。
- unplugin-auto-import 需开启
-
Git 忽略生成文件:
在
.gitignore中加入:plaintext
src/auto-imports.d.ts src/components.d.ts .eslintrc-auto-import.json这些文件可由项目构建时自动生成,无需提交到仓库。
unplugin-vue-components:组件自动“找上门”,import语句说拜拜
vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
AutoImport({
imports: ['vue', 'vue-router', 'pinia'],
dts: 'src/auto-imports.d.ts',
dirs: ['src/composables', 'src/hooks'],
// 解决ESLint报错
eslintrc: {
enabled: true,
filepath: './.eslintrc-auto-import.json',
},
}),
// 自动导入组件
Components({
dirs: ['src/components', 'src/views/components'], // 多组件目录
resolvers: [
ElementPlusResolver(), // Element Plus组件自动导入
],
dts: 'src/components.d.ts',
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
})根组件
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
我们传入 createApp 的对象实际上是一个组件,每个应用都需要一个“根组件”,其他组件将作为其子组件。
挂载应用
应用实例必须在调用了 .mount() 方法后才会渲染出来。该方法接收一个“容器”参数,可以是一个实际的 DOM 元素或是一个 CSS 选择器字符串:
createApp(App).mount('#app')
应用根组件的内容将会被渲染在容器元素里面。容器元素自己将不会被视为应用的一部分。
.mount() 方法应该始终在整个应用配置和资源注册完成后被调用。同时请注意,不同于其他资源注册方法,它的返回值是根组件实例而非应用实例。
应用配置
应用实例会暴露一个 .config 对象允许我们配置一些应用级的选项,例如定义一个应用级的错误处理器,用来捕获所有子组件上的错误:
app.config.errorHandler = (err) => {
/* 处理错误 */
}
应用实例还提供了一些方法来注册应用范围内可用的资源,例如注册一个组件:
app.component('TodoDeleteButton', TodoDeleteButton)
这使得 TodoDeleteButton 在应用的任何地方都是可用的。我们会在指南的后续章节中讨论关于组件和其他资源的注册。你也可以在 API 参考中浏览应用实例 API 的完整列表。
确保在挂载应用实例之前完成所有应用配置!
先来一个简单的例子
<template>
<div>
<h2>Name: {{ name }}</h2>
<p>Age: {{ age }}</p>
<button @click="changeName">修改</button>
<button @click="showTel">查看联系方式</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
// 响应式状态
let name = ref('张三')
let age = ref(18)
let tel = ref('13800000000')
function showTel() {
console.log(tel.value)
}
function changeName() {
name.value = '李四'
}
</script>
模板引用
https://cn.vuejs.org/guide/essentials/template-refs.html#ref-on-component
虽然链接访问仍有问题,但我可以根据 Vue.js 的核心知识,为你详细总结 模板引用(Template Refs)在组件上使用 的核心概念、用法和关键要点。
核心概念:什么是组件上的 ref?
在 Vue 中,ref 用于直接访问另一个组件实例的属性和方法。这打破了 Vue 默认的“自上而下”数据流,是一种必要的逃生舱,用于父组件需要直接操作子组件等特定场景。
详细要点与用法
1. 基本用法
- 声明:在父组件的模板中,通过在子组件标签上使用
ref属性来声明。<template> <ChildComponent ref="childRef" /> </template> - 访问:在
<script setup>中,需要先声明一个同名的 ref 变量,该变量会在组件挂载后自动指向子组件实例。<script setup> import { ref, onMounted } from 'vue' import ChildComponent from './ChildComponent.vue' const childRef = ref(null) // 变量名必须与模板中的 ref 值一致 onMounted(() => { // 现在 childRef.value 就是子组件实例 console.log(childRef.value) }) </script>
2. 访问什么?(子组件的暴露)
父组件只能访问子组件显式暴露(expose) 的内容。
- 默认情况:使用
<script setup>的子组件是默认关闭的,父组件只能访问到子组件通过defineExpose宏显式暴露的内容。// ChildComponent.vue <script setup> import { ref } from 'vue' const internalState = ref('secret') const publicMethod = () => { /* ... */ } // 只有 publicMethod 能被父组件访问到 defineExpose({ publicMethod }) </script> - 选项式API:使用选项式 API 的子组件会自动暴露其所有实例属性(
data,methods,computed等),这可能带来维护上的隐患。
3. 关键注意事项
- 响应式与生命周期:
ref变量是响应式的,但其.value属性只在组件挂载后才有效。操作必须在onMounted或之后的生命周期钩子、事件中进行。 - 避免滥用:过度使用
ref会破坏组件的数据流封装,使应用难以理解和维护。优先考虑使用标准的props和emit进行父子通信。 - 函数型
ref:你可以将ref绑定为一个函数,这在动态生成ref或逻辑复杂的场景下有用。
典型应用场景
为了帮你理解何时该用 ref,可以参考下表:
| 场景 | 描述 | 是否推荐使用 ref |
|---|---|---|
| 操作子组件的 DOM 元素 | 父组件需要直接控制子组件内的输入框聚焦 (focus())、或调用其内部特定元素的浏览器 API。 |
是,这是 ref 的典型用途。 |
| 触发子组件的特定方法 | 父组件需要手动触发子组件的一个复杂动画函数,或一个数据获取方法。 | 视情况,如果可用 emit 事件触发,则优先用 emit。 |
| 获取子组件的数据 | 父组件需要读取子组件内部的一个计算结果或状态。 | 通常不推荐,应优先考虑通过 props 将数据“提升”或使用状态管理。 |
| 替代子组件的状态 | 试图完全从外部控制子组件。 | 不推荐,这严重违背了组件的封装原则。 |
与“元素上的 ref”对比
| 对比项 | 在 HTML 元素上使用 ref |
在 Vue 组件上使用 ref |
|---|---|---|
.value 指向 |
原生的 DOM 元素(如 HTMLInputElement)。 |
子组件的 Vue 组件实例。 |
| 可访问内容 | 该元素的所有 DOM 属性和方法(如 .focus(), .value)。 |
仅限于子组件通过 defineExpose 暴露的属性和方法。 |
| 主要目的 | 直接操作 DOM。 | 直接调用子组件的逻辑。 |
总结
在组件上使用 ref 的核心是:声明一个响应式变量去引用子组件实例,并仅限于操作子组件显式暴露的接口。它是一种强大的直接访问方式,但因破坏了封装性,应谨慎使用,并优先考虑声明式的 props 和 emit 通信。
如果你对特定使用场景(例如与 v-for 结合、或 TypeScript 类型定义)有疑问,我可以提供更具体的解释。
全局API
app.component()
如果同时传递一个组件名字符串及其定义,则注册一个全局组件;如果只传递一个名字,则会返回用该名字注册的组件 (如果存在的话)。
-
类型
interface App { component(name: string): Component | undefined component(name: string, component: Component): this } -
示例
import { createApp } from 'vue' const app = createApp({}) // 注册一个选项对象 app.component('MyComponent', { /* ... */ }) // 得到一个已注册的组件 const MyComponent = app.component('MyComponent')
app.config
每个应用实例都会暴露一个 config 对象,其中包含了对这个应用的配置设定。你可以在挂载应用前更改这些属性 (下面列举了每个属性的对应文档)。
import { createApp } from 'vue'
const app = createApp(/* ... */)
console.log(app.config)

浙公网安备 33010602011771号