一文掌握vue3基础,适合自学入门案例丰富
Vue3
本文从Vue3的基础语法出发,全面系统的介绍了Vue3的核心概念与应用,旨在帮助自学者更轻松地掌握Vue3。文章内容由浅入深,从通过CDN引入Vue3开始,逐步介绍了组合式API、模块化开发、以及常见的Vue3指令和功能并从单个html的使用过渡到 vite ** 项目工程,案例丰富,总结编者学习经验,适合自学vue3。
文章目录
- Vue3
-
- 通过cdn引用vue
- 组合式学习
- 模块化开发
- ref 与 reactive
- 绑定事件 v-on 简写 @
- 显示和隐藏 v-show
- 条件渲染 v-if
- 动态属性绑定v-bind
- v-for 遍历数组和对象
- 双向数据绑定 v-model
- v-model修饰符
- 渲染数据 v-text 和 v-html
- 计算属性computed
- 侦听器watch
- 图片轮播案例
- 记事本案例
- change事件&&购物车案例
- 购物车案例优化
- Axios获取后端数据
- 基于vite创建vue3项目
- vue组件学习
- 父传子defineprops
- 子传父defineEmits
- 跨组件通信-依赖注入
- 匿名插槽和具名插槽
- 作用域插槽
- 生命周期函数
- toRef 和 toRefs
- Pinia简介与安装
- 定义和使用Store
- Pinia持久化存储插件
- 鸣谢
渐进式的javascript框架,我们可以逐步引入vue的功能
通过cdn引用vue
你可以借助 script 标签直接通过 CDN 来使用 Vue:
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
通过 CDN 使用 Vue 时,不涉及“构建步骤”。这使得设置更加简单,并且可以用于增强静态的 HTML 或与后端框架集成。但是,你将无法使用单文件组件 (SFC) 语法。
组合式学习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="vue.global.js"></script>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
<p>{{ web.title }} {{ web.url }}</p>
</div>
<script>
Vue.createApp({
// setup选项,用于设置响应式数据和方法等
setup(){
const message = Vue.ref('Hello Vue!')
// 这是个对象,可以直接在模板中使用
const web = Vue.reactive({
title: 'Vue.js',
url: 'https://cn.vuejs.org/'
})
return {
message: message,
// web: web
web
}
}
}).mount('#app')
</script>
</body>
</html>
模块化开发
使用es
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
<p>{{ web.title }} {{ web.url }}</p>
</div>
<script type="module">
import { createApp , reactive} from './vue.esm-browser.js'
createApp({
// setup选项,用于设置响应式数据和方法等
setup(){
// 这是个对象,可以直接在模板中使用
const web = reactive({
title: 'Vue.js',
url: 'https://cn.vuejs.org/'
})
return {
message: 'Hello Vue.js',
// web: web
web
}
}
}).mount('#app')
</script>
</body>
</html>
ref 与 reactive

ref是一个引用,修改使用.value, 而reactive则直接修改对应属性即可
ref也可以存储数组
绑定事件 v-on 简写 @

显示和隐藏 v-show
<p v-show="show">...</p>
当show为false就隐藏
条件渲染 v-if
<p v-if="show"> ... </p>
不适用于频繁切换显示状态
以下是更好的用法
<p v-if="show < 1000">用户较少</p>
<p v-else-if="show > 1000 && show < 10000 ">用户较多</p>
<p v-else>用户很多</p>
动态属性绑定v-bind
<input type="text" :value="web.url">
这样文本框的值就是web.url的值
简写直接用:
这个绑定可以用在class, img, src等用法,实现其值的动态绑定
放在li中为每行元素设置title和key
:title=“value.name”
:key=“value.id”
v-for 遍历数组和对象
<p>遍历数组或对象</p>
<ul>
<li v-for="value in arr">{{ value }}</li>
</ul>
const arr = Vue.reactive([1,2,3,4,5])
双向数据绑定 v- model
单向数据绑定:当数据发生改变时,视图会自动更新,但是用户手动修改input的值,数据不会自动更新
双向数据绑定会自动更新数据的值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="vue.global.js"></script>
</head>
<body>
<div id="app">
<h3>文本框 {{ data.text }}</h3>
<h3>单选框 {{ data.radio }}</h3>
<h3>多选框 {{ data.checkbox }}</h3>
<h3>下拉框 {{ data.select }}</h3>
<h3>记住密码 {{ data.remember }}</h3>
双向数据绑定 <input type="text" v-model="data.text">
<br>
<input type="radio" value="male" v-model="data.radio"> 男
<input type="radio" value="female" v-model="data.radio"> 女
<br>
<input type="checkbox" value="apple" v-model="data.checkbox"> 苹果
<input type="checkbox" value="banana" v-model="data.checkbox"> 香蕉
<input type="checkbox" value="orange" v-model="data.checkbox"> 橘子
<br>
<select v-model="data.select">
<option value="">请选择</option>
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="orange">橘子</option>
</select>
<br>
<input type="checkbox" v-model="data.remember"> 记住密码
</div>
<script>
Vue.createApp({
// setup选项,用于设置响应式数据和方法等
setup() {
const data = Vue.reactive({
text: 'hello',
radio: '',
checkbox: [],
select: '',
remember: false
})
return {
data
}
}
}).mount('#app')
</script>
</body>
</html>
v-model修饰符
之前的双向数据绑定是实时渲染的(默认形式),现在我们不需要实时渲染,只要按enter等才改
- 在失去焦点或enter后修改 v-model.lazy
- 输入框的值转为数字类型 v-model.number
- 去除首尾空格 v-model.trim
以上是常用的三种
渲染数据 v-text 和 v-html
v-html可以将数据解析为html格式,而v-text会解析为纯文本格式
计算属性computed

可以避免重复计算
侦听器watch
监听元素的变化
setup(){
const date = reactive({
year:2023,
month:10
})
watch(date.year, (newValue, oldValue))=>{
console.log("new:", newValue, "old:", oldValue);
}
}
// 注意,json中对象和数组是通过引用传递的,所以old也是修改后的值,如果是普通变量,则会通过赋值传递,会保留old值
自动监听watchEffect

将不需要手动设定监听的对象
图片轮播案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="vue.global.js"></script>
</head>
<body>
<div id="app">
<h1>{{number}}</h1>
<h1>imageSrc: {{imageSrc}}</h1>
<img :src="imageSrc" style="width: 300px;"> <br>
<button @click="next">+</button>
<button @click="prev">-</button>
<ul>
<li v-for="value in 6">
<button @click="jump(value)">{{value}}</a>
</li>
</ul>
</div>
<script>
Vue.createApp({
// setup选项,用于设置响应式数据和方法等
setup() {
const number = Vue.ref(1)
// 这是个对象,可以直接在模板中使用
const next = () => {
number.value++
if (number.value == 6) {
number.value = 1
}
}
const prev = () => {
number.value--
if (number.value == 1) {
number.value = 6
}
}
const web = Vue.reactive({
title: 'Vue.js',
url: 'https://cn.vuejs.org/'
})
const imageSrc = Vue.computed(() => {
return `image/${number.value}.jpg`
})
const jump = (value) => {
number.value = value
}
return {
number,
next,
// web: web
imageSrc,
prev,
jump,
web
}
}
}).mount('#app')
</script>
</script>
</body>
</html>
记事本案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>记事本</title>
<script src="vue.global.js"></script>
</head>
</head>
<body>
<div id="app">
<input type="text" v-model="data.content">
<button @click="add">添加</button>
<ul>
<li v-for="(value, index) in data.list" :key="index">{{value}}
<button @click="remove(index)">删除</button>
</li>
{{data.list.length}}
<button @click="clean">清空</button>
</ul>
</div>
<script>
Vue.createApp({
setup(){
const data = Vue.reactive({
content: '',
list: ["· 吃饭", "· 睡觉", "· 打豆豆"]
})
const add = () =>{
data.list.push(data.content)
console.log(data.list)
}
const remove = (index) =>{
data.list.splice(index, 1)
console.log(data.list)
}
const clean = () =>{
data.list = []
console.log(data.list)
}
return {
data,
add,
remove,
clean
}
}
}).mount('#app')
</script>
</body>
</html>
change事件&&购物车案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>购物车</title>
<script src="vue.global.js"></script>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<td><input type="checkbox" v-model="data.seleted" @change="selectAll"></td>
<td>商品名称</td>
<td>商品价格</td>
<td>库存</td>
<td colspan="2">操作</td>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in data.list">
<td><input type="checkbox" :value="item" v-model="data.checkboxList" @change="checkSelected"></td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>{{item.stock}}</td>
<td><button @click="add(index)">+</button></td>
<td>{{item.number}}</td>
<td><button @click="reduce(index)">-</button></td>
<td><button @click="del(item.id)">删除</button></td>
</tr>
</tbody>
<tfoot>
<tr>
<td>总价 {{totalPrice()}}</td>
</tr>
</tfoot>
</table>
</div>
<script>
Vue.createApp({
setup() {
const data = Vue.reactive({
seleted: false,
checkboxList: [],
list: [{
id: 1,
name: '商品1',
price: 100,
number: 0,
stock: 3
},
{
id: 2,
name: '商品2',
price: 200,
number: 0,
stock: 2
},
{
id: 3,
name: '商品3',
price: 300,
number: 0,
stock: 1
},
{
id: 4,
name: '商品4',
price: 400,
number: 0,
stock: 4
},
{
id: 5,
name: '商品5',
price: 500,
number: 0,
stock: 5
}
]
})
const selectAll = () => {
console.log(data.seleted)
if (data.seleted) {
data.checkboxList = data.list
} else {
data.checkboxList = []
}
console.log(data.checkboxList)
}
const checkSelected = () => {
if (data.checkboxList.length == data.list.length && data.list.length != 0) {
data.seleted = true
} else {
data.seleted = false
}
}
const totalPrice = () => {
let total = 0;
for (let i = 0; i < data.checkboxList.length; i++) {
total += data.list[i].price * data.list[i].number
}
return total
}
const add = (index) => {
if (data.list[index].number < data.list[index].stock)
data.list[index].number++;
}
const reduce = (index) => {
if (data.list[index].number > 0) {
data.list[index].number--;
}
}
const del = (id) => {
for (let i = 0; i < data.list.length; i++) {
if (data.list[i].id == id) {
data.list.splice(i, 1)
break;
}
}
for(let i = 0; i < data.checkboxList.length; i++){
if(data.checkboxList[i].id == id){
data.checkboxList.splice(i, 1)
break;
}
}
checkSelected()
}
return {
data,
selectAll,
checkSelected,
totalPrice,
add,
reduce,
del
}
}
}).mount('#app')
</script>
</body>
</</sp[Truncated]