1. 特性
声明式、响应式、组件化
2. 环境搭建
2.1. 安装Node.js
node -v
npm -v3. 创建项目
3.1. 安装官方脚手架并创建项目
npm create vue@latest3.2. 目录解释

node_modules: 项目依赖包文件夹,比如通过npm install 包名安装的包都会放在这个目录下;public: 公共资源目录,用于存放公共资源,如favicon.ico图标等;index.html: 首页;package.json: 项目描述以及依赖;package-lock.json: 版本管理使用的文件;README.md: 用于项目描述的 markdown 文档;src: 核心文件目录,源码都放在这里面;
进入 src 文件夹

assets: 静态资源目录,用于存放样式、图片、字体等;components: 组件文件夹,通用的组件存放目录;App.vue: 主组件,也是页面的入口文件,所有页面都是在 App.vue 下进行路由切换的;main.js: 入口 Javascript 文件;

3.3. 启动项目
# 安装项目所需依赖
npm install
# 启动项目
npm run dev3.4. 打包项目
npm run build执行成功后,会在项目文件夹中看到多了一个 dist 文件夹

该文件下放置的就是编译后的静态文件,如 html、css、js 等相关文件

4. 语法
4.1. {{ }}插值表达式
插值表达式支持四则运算、比较运算符、数值操作、三目运算符、数组操作、对象操作等
<template>
<!-- 字符串 -->
<div>{{ obj.title }}</div>
<div>{{ obj.num + "犬小哈教程" }}</div>
<div>{{ obj.title.length }}</div>
<!-- 数值 -->
<div>{{ obj.num }}</div>
<div>{{ obj.num + obj.num2 }}</div>
<div>{{ obj.num > obj.num2 }}</div>
<div>{{ obj.num.toFixed(2) }}</div>
<!-- 布尔类型 -->
<div>{{ obj.isSuccess }}</div>
<!-- 数组 -->
<div>{{ obj.arr }}</div>
<!-- 对象 -->
<div>{{ obj.subObj }}</div>
<div>{{ obj.subObj.domain }}</div>
<!-- 三目运算符 -->
<div>{{ obj.isSuccess ? 'true' : 'false' }}</div>
</template>
<script setup>
import { reactive } from 'vue';
// reactive 函数用于响应式对象
const obj = reactive({
title: 'Hello',
num: 1,
num2: 2,
isSuccess: true,
arr: [1, 2, 3, 4],
subObj: {
title: '犬小哈',
domain: 'www.quanxiaoha.com'
}
})
</script>
4.2. reactive和ref创建响应式数据的两种方式
reactive 和 ref 的主要区别对比
注:ref 在用于对象时,其内部会自动调用 reactive 转为代理对象 。
官方推荐优先使用 ref,因其更灵活且避免 reactive 的常见陷阱 。
4.3. v-text指令:文本插值
<template>
<div>
<!-- v-text文本插值 -->
<div v-text="obj.title"></div>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
// reactive 函数用于响应式对象
const obj = ref({
title: 'Hello',
num: 1,
num2: 2,
isSuccess: true,
arr: [1, 2, 3, 4],
subObj: {
title: '犬小哈',
domain: 'www.quanxiaoha.com'
}
})
</script>
<style scoped>
</style>
4.4. v-once指令:只会执行一次
<template>
<div>
<!-- v-once只会执行一次 -->
<div v-once>{{ input }}</div>
<div>{{ input }}</div>
<input v-model="input">
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const input = ref('测试v-once');
</script>
<style scoped>
</style>
4.5. v-html指令:文本插值,解析html代码
<template>
<div>
<!-- v-html解析html代码 -->
<div v-html="htmlText"></div>
<div v-text="htmlText"></div>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const htmlText = ref('<div>HTML</div>');
</script>
<style scoped>
</style>
4.6. v-bind指令:属性绑定
v-bind 指令可用于绑定 HTML 属性,它们包括 class 、 src 、title 等等
<template>
<div>
<!-- v-bind属性绑定 -->
<a v-bind:href="linksUrl">link</a>
<!-- v-bind简写形式 -->
<a :href="linksUrl">link</a>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const linksUrl = ref('https://www.baidu.com');
</script>
<style scoped>
</style>
4.6.1. 绑定css样式
<template>
<div>
<!-- 绑定css样式 -->
<div class = "black" :class="{ red: isActive }">绑定css样式</div>
<input v-model="isActive"></input>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const isActive = ref(true);
</script>
<style scoped>
.black {
color: black;
}
.red {
color: red;
}
</style>
{ red: isActive } 是Vue的对象语法,用于根据 isActive 的布尔值来决定是否给元素添加 red 这个CSS类名。后添加的class会覆盖前面同等级的class。
4.6.2. 通过数组绑定多个样式
<template>
<div>
<!-- 通过数组绑定多个样式 -->
<p :class="[classes.color, classes.fontSize, classes.background]">通过数组绑定多个样式</p>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const classes = ref({
color: 'red',
fontSize: '20px',
background: 'yellow'
})
</script>
<style scoped>
.black {
color: black;
}
.red {
color: red;
}
</style>
4.6.3. 通过三目运算绑定css样式
<template>
<div>
<!-- 通过三目运算绑定样式 -->
<p :class="isActive ? 'red' : ''">通过三目运算绑定样式</p>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const isActive = ref(true);
</script>
<style scoped>
.black {
color: black;
}
.red {
color: red;
}
</style>
4.7. v-if指令:条件渲染
<template>
<div>
<!-- vi-if条件渲染 -->
<div v-if="isShow">vi-if条件渲染</div>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const isShow = ref(true);
</script>
<style scoped>
</style>
4.7.1. v-else指令
<template>
<div>
<!-- vi-if条件渲染 -->
<div v-if="isShow">vi-if条件渲染</div>
<div v-else>v-else渲染</div>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const isShow = ref(false);
</script>
<style scoped>
</style>
4.7.2. v-else-if指令
<template>
<div>
<!-- vi-if条件渲染 -->
<div v-if="isShow === 1">vi-if条件渲染</div>
<div v-else-if="isShow === 2">v-else-if渲染</div>
<div v-else>v-else渲染</div>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const isShow = ref(3);
</script>
<style scoped>
</style>
4.8. v-show指令:显示与隐藏
<template>
<div>
<!-- v-show指令 -->
<div v-show="isShow === 1">v-show指令</div>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const isShow = ref(3);
</script>
<style scoped>
</style>
<div data-v-7a7a37b1="" style="display: none;">v-show指令</div>
4.9. v-for指令:循环
<template>
<div>
<!-- v-for -->
<table border="1">
<thead>
<tr>
<th>序号</th>
<th>名称</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in list" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ item }}</td>
</tr>
</tbody>
</table>
</template>
<script setup>
import {reactive, ref} from 'vue';
const list = ref(["JS", "Vue", "Java", "Python"]);
</script>
<style scoped>
</style>:key="index" 可为每项提供一个唯一 key 属性,目的是为了方便的跟踪每个节点,这对重用和重新排列现有元素非常有帮助。
4.9.1. 遍历对象数组
<template>
<h1>犬小哈教程列表</h1>
<table border="1" width="600px">
<tr>
<td>ID</td>
<td>名称</td>
<td>阅读量</td>
</tr>
<tr v-for="(tutorial, index) in tutorials" :key="index">
<td>{{ tutorial.id }}</td>
<td>{{ tutorial.name }}</td>
<td>{{ tutorial.viewNum }}</td>
</tr>
</table>
</template>
<script setup>
import { reactive } from 'vue'
// 定义一个教程列表数组, 元素为对象,包含 ID、教程名称、被阅读数 3 个字段
const tutorials = reactive([
{id: 1, name: "Vue 3 教程", viewNum: "12092"},
{id: 2, name: "IDEA 教程", viewNum: "90236"},
{id: 3, name: "Docker 教程", viewNum: "5902"},
])
</script>
4.9.2. 遍历
<template>
<p v-for="(value, key, index) in tutorial" :key="index">
字段名:{{ key }},字段值:{{ value }}
</p>
</template>
<script setup>
import { reactive } from 'vue'
// 定义一个对象,包含 ID、教程名称、被阅读数 3 个字段
const tutorial = reactive({id: 1, name: "Vue 3 教程", viewNum: "12092"},)
</script>
4.10. v-on指令:绑定事件监听
<template>
<div>
<!-- v-on事件监听 -->
<button v-on:click="onClick">点击</button>
<!-- v-on简写形式 -->
<button @click="onClick">点击</button>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const onClick = () => {
alert("onClick")
}
</script>
<style scoped>
</style>
4.10.1. 参数传递
<template>
<div>
<!-- v-on事件监听 -->
<button v-on:click="onClick('Hello')">点击</button>
<button @click="onClick('World')">点击</button>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const onClick = (value) => {
alert("onClick:" + value)
}
</script>
<style scoped>
</style>
4.10.2. 事件详情
<template>
<div>
<!-- v-on事件监听 -->
<button v-on:click="onClick($event, 'Hello')">点击</button>
<button @click="onClick($event, 'World')">点击</button>
<button @click="showMousePosition">显示鼠标坐标</button>
</div>
</template>
<script setup>
import {reactive, ref} from 'vue';
const showMousePosition = (event) => {
alert(`鼠标坐标为:${event.clientX}, ${event.clientY}`)
}
const onClick = (event, value) => {
alert(`onClick:${event.clientX}` + value)
}
</script>
<style scoped>
</style>
注意使用反撇号`
4.10.3. 事件修饰符
.stop:阻止事件冒泡。.prevent:阻止事件的默认行为。.capture:事件捕获模式,事件从外部元素向内部元素传播时触发。.self:只在当前元素自身触发事件时才调用事件处理函数。.once:事件只会触发一次。
<!-- 阻止单击事件冒泡 -->
<a @click.stop="clickMe"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 添加事件侦听器时使用事件捕获模式 -->
<div @click.capture="clickTwo"></div>
<!-- 只有当事件在该元素本身(非子元素)触发时触发回调 -->
<div @click.self="clickThree"></div>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 修饰符串联模式 -->
<a @click.stop.prevent="clickFour"></a>
<template>
<a href="https://www.quanxiaoha.com">犬小哈教程</a><br>
<a href="https://www.quanxiaoha.com" @click.prevent="goXiaohaWebsit1">犬小哈教程</a><br>
<a href="https://www.quanxiaoha.com" @click="goXiaohaWebsit2($event)">犬小哈教程</a>
</template>
<script setup>
const goXiaohaWebsit1 = () => {
}
const goXiaohaWebsit2 = (e) => {
// 阻止
e.preventDefault();
}
</script>
上述代码中,只有第一个链接可以正常跳转,后面两个链接都被阻止了。
4.11. 按键修饰符
可以使用按键修饰符来监听键盘事件,并执行相应的事件处理函数。按键修饰符可以帮助你更精确地控制用户与你的应用程序的交互。
以下是一些常用的按键修饰符和它们对应的功能:
这些修饰符可以与 @keyup 或 @keydown 等事件监听器一起使用,以监听特定键盘事件,并执行相应的操作。
<template>
<input @keyup.enter="handleEnterKey"/>
<p>{{ message }}</p>
</template>
<script setup>
import { ref } from 'vue';
const message = ref('')
// 回车键对应事件
const handleEnterKey = () => {
message.value = '您按了回车键了'
}
</script>
4.12. v-model指令:双向绑定
4.12.1. 文本框双向绑定
<template>
<div>
<input v-model="message" placeholder="请输入内容" />
<p>你输入的内容是:{{ message }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const message = ref('')
</script>
4.12.2. 复选框双向绑定
<template>
<div>
兴趣爱好:
<input type="checkbox" v-model="interests" value="唱"/><label>唱🎤</label>
<input type="checkbox" v-model="interests" value="跳"/><label>跳</label>
<input type="checkbox" v-model="interests" value="Rapper"/><label>Rapper</label>
<input type="checkbox" v-model="interests" value="篮球"/><label>篮球🏀</label>
<p>您的爱好是:{{ interests }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const interests = ref([])
</script>
4.12.3. 单选框双向绑定
<template>
<div>
性别:
<input type="radio" v-model="sex" value="女"/><label>女</label>
<input type="radio" v-model="sex" value="男"/><label>男</label>
<p>您的性别是:{{ sex }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const sex = ref('')
</script>
4.12.4. 下拉框双向绑定
<template>
<div>
<select v-model="selected">
<option disabled value="">---请选择---</option>
<option value="1">《犬小哈教程》</option>
<option value="2">《Docker 教程》</option>
<option value="3">《Vue 3 教程》</option>
</select>
<p>您选择的是:{{ selected }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const selected = ref(1)
</script>
4.13. 计算属性
使用场景:
数据过滤和排序:根据特定条件过滤或排序数据。
动态类名和样式:根据状态动态添加 CSS 类或样式。
动态表单验证:根据用户输入实时验证表单数据。
复杂逻辑的处理:处理需要依赖多个属性或状态的复杂业务逻辑。
动态计算属性:根据条件动态生成计算属性。
数据映射和转换:将原始数据转换成展示需要的格式。
嵌套数据的处理:处理嵌套结构的数据,提取或计算所需的属性。
权限控制:根据用户权限显示或隐藏特定的界面元素。
状态管理:将状态进行计算,返回派生状态。
实时搜索和过滤:根据搜索词实时过滤显示的数据。
复杂动画逻辑:计算动画的开始、结束状态等属性。
实时统计和分析:实时计算数据的总数、平均值、最大值等。
在这个例子中,discountedPrice 是一个计算属性,它依赖于 goods 商品对象中的 price 和 discount 两个属性的值。当 price 或 discount 发生变化时,discountedPrice 会自动重新计算,并渲染到页面中。
<template>
<div>
<p>商品原价:{{ goods.price }}</p>
<p>折扣:<input v-model="goods.discount"></p>
<p>最终价格:{{ discountedPrice }}</p>
</div>
</template>
<script setup>
import { computed, reactive } from 'vue';
const goods = reactive({
// 原价
price: 100,
// 折扣价
discount: 0.1
})
// 最终价格
const discountedPrice = computed(() => goods.price * (1 - goods.discount))
</script>
在这个例子中,computedBooks 是一个计算属性,它依赖于 searchText 查询关键词这个变量。当 searchText发生变化时,computedBooks 会自动重新计算,从 books 数组中实时筛选出包含对应关键词的数据。
<template>
<div>
<input v-model="searchText" placeholder="请输入查询关键词" />
<ul>
<li v-for="(item, index) in computedBooks" :key="index">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import { computed, ref } from 'vue';
let books = [
'犬小哈教程',
'Java 教程',
'Vue3 项目实战',
'Spring Boot 项目实战',
]
// 查询关键词
const searchText = ref('')
// 筛选后的书籍
const computedBooks = computed(() => {
const newBooks = books.filter(book => book.includes(searchText.value))
return newBooks
})
</script>
计算属性和方法的区别
计算属性适用于依赖多个响应式属性或需要复杂逻辑处理的情况,它具有自动依赖追踪和缓存机制,只有依赖的响应式属性发生变化时才会重新计算。
方法适用于简单的逻辑处理,它不具备缓存机制,每次在模板中使用方法时都会重新执行方法中的逻辑。
选择使用计算属性还是方法取决于你的需求。如果你的逻辑是简单的,而且不需要缓存,可以使用方法。如果你的逻辑较为复杂,或者需要依赖多个响应式属性,建议使用计算属性,因为它可以提高性能并使代码更加清晰。
4.14. 侦听属性
侦听属性允许你在数据变化时执行一些自定义操作,侦听属性允许你监视一个数据,并在数据变化时执行自定义的操作。这个操作可以是同步的,也可以是异步的,比如异步请求、数据持久化、动画等等。
使用场景
异步操作:侦听属性允许执行异步操作,处理需要与服务器端或其他异步任务交互的逻辑。
自定义逻辑:侦听属性使得你可以在数据变化时触发指定函数,例如触发动画、保存数据等。
动态响应:侦听属性能够动态地响应数据的变化,无需手动监听 DOM 事件或定时器。
使用示例
在这个例子中,我们通过watch选项定义了一个侦听属性,它会监视inputText属性的变化,并在每次变化时打印日志,包括当前值和变更前的老值。
<template>
<div>
<input v-model="inputText">
</div>
</template>
<script setup>
import { ref, watch } from 'vue';
// 输入框内容
const inputText = ref('')
watch(inputText, (newText, oldText) => {
console.log(`新值: ${newText}, 老值: ${oldText}`)
})
</script>
通过侦听属性来实现一个根据用户输入的查询关键词,来筛选对应书本的功能
在这个例子中,通过侦听属性对 searchText 属性监听,每当输入关键词变化时,都会对 books 数组进行筛选,并将包含关键词的书籍赋值给 searchBooks , 最终实现了实时搜索的效果。
<template>
<div>
<input v-model="searchText" placeholder="请输入查询关键词" />
<ul>
<li v-for="(item, index) in searchBooks" :key="index">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import { ref, watch } from 'vue';
const books = [
'犬小哈教程',
'Java 教程',
'Vue3 项目实战',
'Spring Boot 项目实战',
]
// 查询关键词
const searchText = ref('')
// 筛选后的书籍
const searchBooks = ref([])
// 侦听属性
watch(searchText, (s) => {
searchBooks.value = books.filter(book => book.includes(s))
})
</script>
5. 路由
Vue 官方提供的路由管理器 —— Vue Router。功能包括:
嵌套路由映射
动态路由选择
模块化、基于组件的路由配置
路由参数、查询、通配符
展示由 Vue.js 的过渡系统提供的过渡效果
细致的导航控制
自动激活 CSS 类的链接
HTML5 history 模式或 hash 模式
可定制的滚动行为
URL 的正确编码
5.1. 安装Vue Router
npm install vue-router5.2. 路由模式
Vue Router 提供了两种主要的路由模式,分别是:
Hash 模式 :#号
History 模式:不带#号
5.3. Demo
创配置路由:建路由js文件(@/router/index.js文件)
// 从 vue-router 中引入 createRouter, createWebHashHistory 方法
import { createRouter, createWebHashHistory } from 'vue-router'
// 引入组件
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
// 定义一个路由数组,统一管理路由
const routes = [
{
path: '/', // 路由地址:首页
name: 'home', // 命名路由
component: Home // 对应的组件
},
{
path: '/login', // 登录页
name: 'login',
component: Login // 对应的组件
}
// ...
]
// 使用 createRouter 方法创建路由实例
const router = createRouter({
history: createWebHashHistory(), // 指定 history 模式,这里采用的是 hash 模式
routes // 定义路由数组,相当于 routes: routes 的简写模式
})
// ES6 模块导出语句,它用于将 router 对象导出,以便其他文件可以导入和使用这个对象
export default router
添加路由填充位:App.vue
<template>
<router-view></router-view>
</template>
<script setup>
</script>
<style scoped>
</style>应用路由:main.js
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
// 从 router 文件夹下引入路由实例
import router from './router'
createApp(App)
.use(router)
.mount('#app')
评论区