Vue3快速入门

news/发布时间2024/5/15 22:57:43

资料

邓睿编程
【2024最新版】3小时学会Vue3,小白零基础视频教程,web前端快速入门实战课程
Vue3快速入门2 -案例篇
Vue.js - 渐进式 JavaScript 框架

Vue3快速入门

1.创建一个 vue 应用程序

"渐进式"是指可以按需引入Vue.js的部分功能, 而不必全量引入整个框架html
<div id="app">{{ msg }}<h2>{{ web.title }}</h2><h3>{{ web.url }}</h3>
</div>js
/*<div id="app"></div> 指定一个 id 为 app 的 div 元素{{ }} 插值表达式, 可以将 Vue 实例中定义的数据在视图中进行渲染如: Vue 实例中定义一个 msg 变量, 值为 "Hello world", 在模板中若使用插值表达式 {{ msg }} 则会被渲染成 "Hello world"响应式数据是指当数据发生变化时, 模板中依赖于该数据的部分会自动更新
*//*//创建一个 Vue 应用程序Vue.createApp({//Composition API(组合式 API) 的 setup选项 用于设置响应式数据和方法等setup() {//Composition API 的 reactive()函数 用于创建响应式数据const web = Vue.reactive({ //Vue.reactive 创建一个响应式数据对象 web, 其中包含 title 和 url 属性title: "邓瑞编程",url: "dengruicode.com"})//返回数据return {msg: "success",web}}}).mount("#app") //将 Vue 应用程序挂载(mount) 到 app 元素上
*///将 Vue 对象中的 createApp、reactive 属性赋值给 createApp、reactive 变量
const { createApp, reactive } = Vue //解构赋值语法createApp({setup() {const web = reactive({title: "邓瑞编程",url: "dengruicode.com"})return {msg: "success",web}}
}).mount("#app")

2.模块化开发

html
<div id="app">{{ msg }}<h2>{{ web.title }}</h2><h3>{{ web.url }}</h3>
</div>
js
<script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({title: "邓瑞编程",url: "dengruicode.com"})return {msg:"success",web}}}).mount("#app")
</script>VSCode 扩展Live Server

3.ref和reactive

html
<div id="app">msg: {{ msg }}<h3>web.title: {{ web.title }}</h3><h3>web.url: {{ web.url }}</h3><h3>web.number: {{ number }}</h3>
</div>
js
<script type="module">import { createApp, ref, reactive } from './vue.esm-browser.js'createApp({setup() {const number = ref(10) //ref用于存储单个基本类型的数据, 如:数字、字符串等number.value = 20 //使用ref创建的响应式对象, 需要通过.value属性来访问和修改其值const web = reactive({ //用于存储复杂数据类型, 如:对象或数组等title: "邓瑞编程",url: "dengruicode.com"})web.url = "www.dengruicode.com" //使用reactive创建的响应式对象, 可以直接通过属性名来访问和修改值return {msg: "success",number,web}}}).mount("#app")
</script>

4.绑定事件 v-on 简写@

html
<div id="app"><h3>{{ msg }}</h3><h3>{{ web.url }}</h3><h3>{{ web.user }}</h3><h3>{{ sub(100, 20) }}</h3><!-- v-on:click 表示在 button 元素上监听 click 事件 --><button v-on:click="edit">修改</button> <br><!-- @click 简写形式 --><button @click="add(20, 30)">加法</button> <br><!-- enter space tab 按键修饰符keyup是在用户松开按键时才触发keydown是在用户按下按键时立即触发-->回车 <input type="text" @keyup.enter="add(40, 60)"> <br>空格 <input type="text" @keyup.space="add(20, 30)"> <br>Tab <input type="text" @keydown.tab="add(10, 20)"> <br>w <input type="text" @keyup.w="add(5, 10)"> <br><!-- 组合快捷键 -->Ctrl + Enter <input type="text" @keyup.ctrl.enter="add(40, 60)"> <br>Ctrl + A <input type="text" @keyup.ctrl.a="add(20, 30)">
</div>
js
<script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({title: "邓瑞编程",url: "dengruicode.com",user: 0})const edit = () => {web.url = "www.dengruicode.com"//msg = "邓瑞编程" //错误示例 不能直接改变msg的值,因为msg是一个普通变量, 不是响应式数据}const add = (a, b) => {web.user += a + b}const sub = (a, b) => {return a - b}return {msg: "success", //普通变量, 非响应式数据, 在模板中普通变量不会自动更新web, //响应式数据edit, //方法add,sub,}}}).mount("#app")</script>

5.显示和隐藏 v-show

html
<div id="app"><h3>{{ web.show }}</h3><p v-show="web.show">邓瑞编程 dengruicode.com</p><button @click="toggle">点击切换显示状态</button>
</div>
js
<script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({show: true})const toggle = () => {web.show = !web.show}return {web,toggle}}}).mount("#app")</script>

6.条件渲染 v-if

html
<div id="app"><h3>{{ web.show }}</h3><p v-show="web.show">邓瑞编程</p><p v-if="web.show">dengruicode.com</p><button @click="toggle">点击切换显示状态</button><p v-if="web.user < 1000">新网站</p><p v-else-if="web.user >= 1000 && web.user < 10000">优秀网站</p><p v-else-if="web.user >= 10000 && web.user < 100000">资深网站</p><p v-else>超级网站</p>
</div>
js
<script type="module">/*v-show 通过 css display属性 来控制元素的显示或隐藏v-if 用于对元素进行条件渲染. 当条件为 true 时, 渲染该元素, 为 false 时, 则不渲染v-show 适用于频繁切换元素的显示状态, 因为只改变 display 属性, 不需要重新渲染整个组件v-if 适用于较少改变的场景, 因为频繁从 dom 中删除或添加元素, 会导致性能下降*/import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({show: true,user: 500})const toggle = () => {web.show = !web.show}return {web,toggle}}}).mount("#app")
</script>

7.动态属性绑定 v-bind 简写:

html
<div id="app"><!-- :value --><h3>value="dengruicode.com"</h3><input type="text" value="dengruicode.com"><h3>v-bind:value="web.url"</h3><input type="text" v-bind:value="web.url"><h3>简写 :value="web.url"</h3><input type="text" :value="web.url"><!-- :src --><h3>src="windows.jpg"</h3><img src="windows.jpg"><h3>:src="web.img"</h3><img :src="web.img"><!-- :class --><h3>class="textColor"</h3><b class="textColor">邓瑞编程</b><h3>:class="{textColor:web.fontStatus}"</h3><b :class="{textColor:web.fontStatus}">dengruicode.com</b>
</div>
js
<script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({url: "www.dengruicode.com",img: "windows.jpg",fontStatus: true})return {web}}}).mount("#app")
</script>

8.遍历数组或对象 v-for

html
<div id="app"><ul><li v-for="(value, index) in data.number">index=> {{ index }} : value=> {{ value }}</li></ul><ul><li v-for="value in data.user">value=> {{ value }}</li></ul><ul><li v-for="(value, key) in data.user">key=> {{ key }} : value=> {{ value }}</li></ul><ul><li v-for="(value, key, index) in data.user">index=> {{ index }} : key=> {{ key }} : value=> {{ value }}</li></ul><ul><!-- <template> 标签可以用来包装多个元素或者多行代码, 不会在页面中渲染  --><template v-for="(value, key, index) in data.user"><li v-if="index == 1">index=> {{ index }} : key=> {{ key }} : value=> {{ value }}</li></template></ul><ul><!-- :key="value.id" 为 每个 li 元素设置一个唯一的 key 值 --><li v-for="(value, index) in data.teacher" :title="value.name" :key="value.id">index=> {{ index }} : value.id=>{{ value.id }} value.name=>{{ value.name }} value.web=>{{ value.web }}</li></ul>
</div>
js
<script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({number: ["十", "十一", "十二"], //数组user: { //对象name: "Luna",gender: "女"},teacher: [ //包含两个对象的数组{ id: 100, name: "邓瑞", web: "dengruicode.com" },{ id: 101, name: "David", web: "www.dengruicode.com" }]})return {data}}}).mount("#app")
</script>

9.双向数据绑定 v-model

html
<div id="app"><h3>文本框 {{ data.text }}</h3><h3>单选框 {{ data.radio }}</h3><h3>复选框 {{ data.checkbox }}</h3><h3>记住密码 {{ data.remember }}</h3><h3>下拉框 {{ data.select }}</h3><!-- 单向数据绑定 当数据发生改变时, 视图会自动更新. 但用户手动更改 input 的值, 数据不会自动更新 -->单向数据绑定 <input type="text" :value="data.text"><hr><!-- 双向数据绑定 当数据发生改变时, 视图会自动更新. 当用户手动更改 input 的值, 数据也会自动更新对于 <input type="text">, v-model 绑定的是 input 元素的 value 属性-->双向数据绑定 <input type="text" v-model="data.text"><hr><!-- 单选框对于 <input type="radio">, v-model 绑定的是 input 元素的选中状态--><input type="radio" v-model="data.radio" value="1">写作<input type="radio" v-model="data.radio" value="2">画画<hr><!-- 复选框对于 <input type="checkbox">, v-model 绑定的是 input 元素的选中状态--><input type="checkbox" v-model="data.checkbox" value="a">写作<input type="checkbox" v-model="data.checkbox" value="b">画画<input type="checkbox" v-model="data.checkbox" value="c">运动<hr><!-- 记住密码 --><input type="checkbox" v-model="data.remember">记住密码<hr><!-- 下拉框对于 <select>, v-model 绑定的是 select 元素的选中状态--><select v-model="data.select"><option value="">请选择</option><option value="A">写作</option><option value="B">画画</option><option value="C">运动</option></select>
</div>
js
<script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({text: "dengruicode.com", //文本框radio: "", //单选框checkbox: [], //复选框remember: false, //单个复选框-记住密码select: "" //下拉框})return {data}}}).mount("#app")
</script>

10.v-model修饰符

html
<div id="app"><h3>文本框 {{ data.text }}</h3><h3>单选框 {{ data.radio }}</h3><h3>复选框 {{ data.checkbox }}</h3><h3>记住密码 {{ data.remember }}</h3><h3>下拉框 {{ data.select }}</h3><!-- 单向数据绑定 当数据发生改变时, 视图会自动更新. 但用户手动更改 input 的值, 数据不会自动更新 -->单向数据绑定 <input type="text" :value="data.text"><hr><!-- 双向数据绑定 当数据发生改变时, 视图会自动更新. 当用户手动更改 input 的值, 数据也会自动更新对于 <input type="text">, v-model 绑定的是 input 元素的 value 属性-->双向数据绑定 <input type="text" v-model="data.text"><hr><!-- 单选框对于 <input type="radio">, v-model 绑定的是 input 元素的选中状态--><input type="radio" v-model="data.radio" value="1">写作<input type="radio" v-model="data.radio" value="2">画画<hr><!-- 复选框对于 <input type="checkbox">, v-model 绑定的是 input 元素的选中状态--><input type="checkbox" v-model="data.checkbox" value="a">写作<input type="checkbox" v-model="data.checkbox" value="b">画画<input type="checkbox" v-model="data.checkbox" value="c">运动<hr><!-- 记住密码 --><input type="checkbox" v-model="data.remember">记住密码<hr><!-- 下拉框对于 <select>, v-model 绑定的是 select 元素的选中状态--><select v-model="data.select"><option value="">请选择</option><option value="A">写作</option><option value="B">画画</option><option value="C">运动</option></select>
</div>
js
<script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({text: "dengruicode.com", //文本框radio: "", //单选框checkbox: [], //复选框remember: false, //单个复选框-记住密码select: "" //下拉框})return {data}}}).mount("#app")
</script>

11.渲染数据 v-text 和 v-html

html
<div id="app"><h3>{{ web.title }}</h3><!-- v-text 将数据解析为纯文本格式 --><h3 v-text="web.title"></h3><!-- v-html 将数据解析为 html 格式 --><h3 v-html="web.url"></h3>
</div>
js
<script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({title: "邓瑞编程",url:"<i style='color:blue;'>www.dengruicode.com</i>"})return {web}}}).mount("#app")
</script>

12.计算属性 computed

html
<div id="app"><h3>add: {{ add() }}</h3><h3>add: {{ add() }}</h3><h3>sum: {{ sum }}</h3><h3>sum: {{ sum }}</h3>x <input type="text" v-model.number="data.x"> <br>y <input type="text" v-model.number="data.y">
</div>
js
<script type="module">import { createApp, reactive, computed } from './vue.esm-browser.js'createApp({setup() {const data = reactive({x: 10,y: 20})//方法-无缓存let add = () => {console.log("add") //打印两次return data.x + data.y}//计算属性-有缓存 [计算属性根据其依赖的响应式数据变化而重新计算]const sum = computed(() => {console.log("sum") //打印一次return data.x + data.y})return {data,sum,add}}}).mount("#app")
</script>

13.侦听器 watch

html
<div id="app">爱好<select v-model="hobby"><option value="">请选择</option><option value="1">写作</option><option value="2">画画</option><option value="3">运动</option></select><hr><select v-model="date.year"><option value="">请选择</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option></select><select v-model="date.month"><option value="">请选择</option><option value="10">10</option><option value="11">11</option><option value="12">12</option></select>
</div>
js
<script type="module">import { createApp, ref, reactive, watch } from './vue.esm-browser.js'createApp({setup() {const hobby = ref("") //爱好const date = reactive({ //日期year: "2023",month: "10"})//监听 hobbywatch(hobby, (newValue, oldValue) => {console.log("oldValue", oldValue, "newValue", newValue)if (newValue == "2") {console.log("画画")}})//监听 datewatch(date, (newValue, oldValue) => {/*JS中对象和数组是通过引用传递的, 而不是通过值传递当修改对象或数组的值时, 实际上修改的是对象或数组的引用, 而不是创建一个新的对象或数组所以,如果修改了对象或数组的值,那么打印出来的结果则是修改后的值*/console.log("oldValue", oldValue, "newValue", newValue)if (newValue.year == "2025") {console.log("2025")}if (newValue.month == "11") {console.log("11")}})//监听 date 中的某个属性 yearwatch(() => date.year, (newValue, oldValue) => {console.log("oldValue", oldValue, "newValue", newValue)if (date.year == "2024") {console.log("2024")}})return {hobby,date}}}).mount("#app")
</script>

14.自动侦听器 watchEffect

html
<div id="app">爱好<select v-model="hobby"><option value="">请选择</option><option value="1">写作</option><option value="2">画画</option><option value="3">运动</option></select><hr><select v-model="date.year"><option value="">请选择</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option></select><select v-model="date.month"><option value="">请选择</option><option value="10">10</option><option value="11">11</option><option value="12">12</option></select>
</div>
js
<script type="module">/*watch需要显式指定要监听的属性, 并且只有当监听的属性发生变化时才会执行若需要更精细地控制或需要获取到原值, 需要使用watch*/import { createApp, ref, reactive, watchEffect } from './vue.esm-browser.js'createApp({setup() {const hobby = ref("") //爱好const date = reactive({ //日期year: "2023",month: "10"})//自动监听watchEffect(() => {console.log("------ 监听开始")if (hobby.value == "2") {console.log("画画")}if (date.year == "2025") {console.log("2025")}if (date.month == "11") {console.log("11")}console.log("------ 监听结束")})return {hobby,date}}}).mount("#app")
</script>

Vue3快速入门2-案例篇

2.图片轮播案例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Title</title>
</head><body><div id="app"><h3>{{ number }}</h3><!-- <img src="/images/1.jpg" style="width: 300px;"> --><img :src=`/images/${number}.jpg` style="width: 300px;"> <hr><button @click="prev">上一张</button><button @click="next">下一张</button><ul><li v-for="(value, index) in 4"><a href="#" @click="jump(value)">{{ value }}</a></li></ul></div><script type="module">import { createApp, ref } from './vue.esm-browser.js'createApp({setup() {const number = ref(1)//上一张const prev = () => {number.value--if (number.value == 0) {number.value = 4}}//下一张const next = () => {number.value++if (number.value == 5) {number.value = 1}}//跳转const jump = (value) => {number.value = value}return {number,prev,next,jump}}}).mount("#app")</script>
</body></html>

3.记事本案例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Title</title>
</head><body><div id="app"><input type="text" v-model="data.content"><button @click="add">添加</button> <hr><ul><li v-for="(value, index) in data.list">{{ value }} <button @click="del(index)">删除</button></li></ul>记录数 {{ data.list.length }} <br><button @click="clear">清空</button></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({content: "",list: ["邓瑞编程", "dengruicode.com"],})//添加const add = () => {if (data.content == "") {alert("请填写内容")return}data.list.push(data.content) //push 向数组末尾添加一个或多个元素data.content = "" //清空文本框}//删除const del = (index) => {data.list.splice(index, 1) //splice(要删除元素的索引位置, 要删除的元素数量)}//清空const clear = () => {data.list = []}return {data,add,del,clear}}}).mount("#app")</script>
</body></html>

4.购物车案例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Title</title><style>table {width: 600px;color: #8f8e8e;text-align: center;border-collapse: collapse;}table thead {background: #F5F5F5;}table tr {height: 30px;line-height: 30px;border: 1px solid #ececec;}</style>
</head><body><div id="app"><table><thead><tr><td><input type="checkbox" v-model="data.selected" @change="selectAll" /></td><td>商品</td><td>单价</td><td>库存</td><td colspan="2">操作</td></tr></thead><tbody><tr v-for="(value, index) in data.list"><td><input type="checkbox" v-model="data.checkboxList" :value="value" @change="checkSelect" /></td><td>{{ value.name }}</td><td>{{ value.price }}</td><td>{{ value.stock }}</td><td><button @click="sub(value)">-</button>{{ value.number }}<button @click="add(value)">+</button></td><td><button @click="del(index,value.id)">删除</button></td></tr></tbody><tfoot><tr><td>总价 {{ totalPrice() }}</td></tr></tfoot></table></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({selected: false,checkboxList: [],list: [{id: 1,name: "铅笔",price: 10,number: 1,stock: 3},{id: 2,name: "鼠标",price: 20,number: 2,stock: 5},{id: 3,name: "键盘",price: 30,number: 1,stock: 6}],})//减const sub = (value) => {value.number--if (value.number <= 1) {value.number = 1}}//加const add = (value) => {value.number++if (value.number >= value.stock) {value.number = value.stock}}//删除const del = (index, id) => {data.list.splice(index, 1) //splice(要删除元素的索引位置, 要删除的元素数量)//filter 筛选符合条件的元素, 返回一个新的数组let newArr = data.checkboxList.filter((value, index) => {return value.id != id})data.checkboxList = newArrcheckSelect() //检查勾选状态}//总价const totalPrice = () => {let total = 0for (let i = 0; i < data.checkboxList.length; i++) {total += data.checkboxList[i].price * data.checkboxList[i].number}return total}//全选/反选const selectAll = () => {if (data.selected) { //truedata.checkboxList = data.list} else { //falsedata.checkboxList = []}}//检查勾选状态const checkSelect = () => {if (data.checkboxList.length != data.list.length || data.list.length == 0) {data.selected = false} else {data.selected = true}}return {data,sub,add,del,totalPrice,selectAll,checkSelect}}}).mount("#app")</script>
</body></html>

5.购物车优化案例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Title</title><style>table {width: 600px;color: #8f8e8e;text-align: center;border-collapse: collapse;}table thead {background: #F5F5F5;}table tr {height: 30px;line-height: 30px;border: 1px solid #ececec;}</style>
</head><body><div id="app"><table><thead><tr><!-- <td><input type="checkbox" v-model="data.selected" @change="selectAll" /></td> --><td><input type="checkbox" v-model="data.selected" /></td><td>商品</td><td>单价</td><td>库存</td><td colspan="2">操作</td></tr></thead><tbody><tr v-for="(value, index) in data.list"><!-- <td><input type="checkbox" v-model="data.checkboxList" :value="value" @change="checkSelect" /></td> --><td><input type="checkbox" v-model="data.checkboxList" :value="value" /></td><td>{{ value.name }}</td><td>{{ value.price }}</td><td>{{ value.stock }}</td><td><button @click="sub(value)">-</button>{{ value.number }}<button @click="add(value)">+</button></td><td><button @click="del(index,value.id)">删除</button></td></tr></tbody><tfoot><tr><!-- <td>总价 {{ totalPrice() }}</td> --><td>总价 {{ totalPrice }}</td></tr></tfoot></table></div><script type="module">import { createApp, reactive, watch, computed } from './vue.esm-browser.js'createApp({setup() {const data = reactive({selected: false,checkboxList: [],list: [{id: 1,name: "铅笔",price: 10,number: 1,stock: 3},{id: 2,name: "鼠标",price: 20,number: 2,stock: 5},{id: 3,name: "键盘",price: 30,number: 1,stock: 6}],})//减const sub = (value) => {value.number--if (value.number <= 1) {value.number = 1}}//加const add = (value) => {value.number++if (value.number >= value.stock) {value.number = value.stock}}//删除const del = (index, id) => {data.list.splice(index, 1) //splice(要删除元素的索引位置, 要删除的元素数量)//filter 筛选符合条件的元素, 返回一个新的数组let newArr = data.checkboxList.filter((value, index) => {return value.id != id})data.checkboxList = newArr//checkSelect() //检查勾选状态}/*//总价const totalPrice = () => {let total = 0for (let i = 0; i < data.checkboxList.length; i++) {total += data.checkboxList[i].price * data.checkboxList[i].number}return total}*///计算属性-有缓存 [计算属性根据其依赖的响应式数据变化而重新计算]const totalPrice = computed(() => {/*reduce定义: 用于对数组中的所有元素进行迭代操作, 并将每次操作的结果累加到一个初始值上reduce接收两个参数: 一个是累加器函数, 另一个是初始值reduce: 将 data.checkboxList 数组中的每个 checkbox 对象的 price 和 number 属性进行相乘, 并将结果累加到初始值 0 上, 最后返回累加的结果total(累加器) 用于存储每次计算的结果, 初始值为 0item(当前元素) 在每次迭代过程中, 当前元素的值会被传递给回调函数*/return data.checkboxList.reduce((total, item) => total + item.price * item.number, 0)})/*//全选/反选const selectAll = () => {if (data.selected) { //truedata.checkboxList = data.list} else { //falsedata.checkboxList = []}}*///监听 data.selectedlet flag = truewatch(() => data.selected, (newValue, oldValue) => {//console.log("newValue:",newValue,"oldValue:",oldValue)if (newValue) {data.checkboxList = data.list} else {if (flag) {data.checkboxList = []}}//console.log(data.checkboxList)})                /*//检查勾选状态const checkSelect = () => {if (data.checkboxList.length == data.list.length && data.list.length != 0) {data.selected = true} else {data.selected = false}}*///监听 data.checkboxListwatch(() => data.checkboxList, (newValue, oldValue) => {console.log("newValue:", newValue, "oldValue:", oldValue)console.log(newValue.length)if (newValue.length == data.list.length && data.list.length != 0) {data.selected = trueflag = true} else {data.selected = falseflag = false}})                return {data,sub,add,del,totalPrice,//selectAll,//checkSelect}}}).mount("#app")</script>
</body></html>

6.使用Axios实现文章搜索案例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/axios.min.js"></script>
</head><body><div id="app"><select v-model="data.type"><option value="0">请选择</option><option value="1">ID</option><option value="2">标题</option></select><input type="text" v-model="data.content"><button @click="search">搜索</button><ul><li v-for="(value, index) in data.list">{{ value }}</li></ul></div><script type="module">import { createApp, reactive } from './js/vue.esm-browser.js'createApp({setup() {const data = reactive({type: "0", //搜索类型content: "", //搜索内容list: [],})//搜索const search = () => {//console.log(data.content)data.list = [] //清空if (data.type == "1") {let id = data.content //参数//get请求axios.get(`http://127.0.0.1/article/get/id/${id}`).then(response => {console.log("get.data:", response.data)if(response.data.status == "success"){if(response.data.data){data.list.push(response.data.data) //push 向数组末尾添加一个或多个元素}}}).catch(error => {console.log("get.error:", error)})} else if (data.type == "2") {//参数let param  = { title: data.content}//post请求 [axios post的默认请求头是 application/json]axios.post('http://127.0.0.1/article/postJson/search', param).then(response => {console.log("postJson.data:", response.data)if(response.data.status == "success"){for(let i=0; i<response.data.data.length; i++){data.list.push(response.data.data[i]) //push 向数组末尾添加一个或多个元素}}}).catch(error => {console.log("postJson.error:", error)})}}return {data,search}}}).mount("#app")</script>
</body></html>

Vue3快速入门3-组件篇

1.基于Vite创建Vue3项目

官网https://cn.vitejs.dev基于Vite创建Vue3项目npm create vite@latestOk to proceed? (y) » yProject name: » demoSelect a framework: » VueSelect a variant: » JavaScriptDone. Now run:cd demonpm installnpm run devLocal: http://localhost:5173删除文件src\style.csssrc\components\HelloWorld.vue删除代码main.jsimport './style.css'修改代码src\App.vue<script setup></script><template>dengruicode.com</template><style scoped></style>

2.Vue3好用的VsCode插件

     Vue Language Features (Volar)TypeScript Vue Plugin (Volar)Vue VSCode Snippets别名路径跳转注Vue VSCode Snippets自定义模板C:\Users\David\.vscode\extensions\sdras.vue-vscode-snippets-3.1.1\snippets模板vbase-3-setupvbase-3-ts-setup重启vscode

3.导入组件

<script setup>//导入子组件//App.vue是父组件,因为它包含了header.vue和footer.vue两个子组件import Header from "./components/header.vue"import Footer from "./components/footer.vue"
</script><template><Header/>dengruicode.com<Footer/>
</template><style scoped></style>

4.父传子 defineProps

App.vue<script setup>import { reactive } from 'vue'//导入子组件//App.vue是父组件,因为它包含了header.vue和footer.vue两个子组件import Header from "./components/header.vue"import Footer from "./components/footer.vue"/*const propsWeb = {user: 10,ip: '127.0.0.1'}*///响应式数据const propsWeb = reactive({user: 10,ip: '127.0.0.1'})//添加用户const userAdd = () => {propsWeb.user++console.log(propsWeb.user)}
</script><template><!-- 父传子 - 方式1 --><Header propsName="邓瑞编程" propsUrl="dengruicode.com" />dengruicode.com<button @click="userAdd">添加用户</button><!-- 父传子 - 方式2 --><!-- <Footer v-bind="propsWeb" /> --><Footer :="propsWeb" />
</template><style scoped></style>header.vue<script setup>//子组件//接收方式1 - 数组/*defineProps是Vue3的编译时宏函数,用于接收父组件向子组件传递的属性(props)注当使用Vue编译器编译包含defineProps的组件时,编译器会将这些宏替换为相应的运行时代码*/const props = defineProps(["propsName","propsUrl"])console.log(props)
</script><template><h3>Header</h3>
</template><style scoped></style>footer.vue<script setup>//子组件//接收方式2 - 对象/*const props = defineProps({user: Number,ip: String})*/const props = defineProps({user: Number,ip: {type: String,required: true, //true表示必传属性,若未传则会提示警告信息default: 'localhost' //未传默认值}})console.log(props)
</script><template><h3>Footer</h3>user: {{ props.user }}
</template><style scoped></style>

5.子传父 defineEmits

App.vue<script setup>import { reactive,ref } from 'vue'//导入子组件import Header from "./components/header.vue"//响应式数据const web = reactive({name: "邓瑞编程",url: 'dengruicode.com'})const user = ref(0)//子传父const emitsWeb = (data) => {console.log("emitsWeb:",data)web.url = data.url}const emitsUser = (data) => {console.log("emitsUser:",data)user.value += data}
</script><template><!-- 子传父 --><Header @web="emitsWeb" @user="emitsUser" />{{ web.url }} - {{ user }}
</template><style scoped></style>header.vue<script setup>//子组件/*defineEmits是Vue3的编译时宏函数,用于子组件向父组件发送自定义事件*///子传父//定义一个名为 emits 的对象, 用于存储自定义事件const emits = defineEmits(["web","user"])//发送名为 web 和 user 的自定义事件emits("web", {name:"邓瑞",url:"www.dengruicode.com"})//添加用户const userAdd = () => {//发送名为 user 的自定义事件emits("user", 10)}
</script><template><h3>Header</h3><button @click="userAdd">添加用户</button>
</template><style scoped></style>

6.跨组件通信-依赖注入

App.vue<script setup>import { provide, ref } from 'vue'//导入子组件import Header from "./components/header.vue"//provide用于父组件将 数据 提供给所有子组件/*若使用了provide和inject来进行数据传递,则一般不需要再使用defineProps*/provide("provideWeb",{name:"邓瑞",url:"www.dengruicode.com"})//传递响应式数据const user = ref(0)provide("provideUser",user)//添加用户const userAdd = () => {user.value++}//用于父组件将 函数 提供给所有子组件provide("provideFuncUserAdd",userAdd)
</script><template><h3>App.vue-Top组件</h3>{{ user }}<!-- 子组件 --><Header/>
</template><style scoped></style>header.vue<script setup>import { provide, inject } from 'vue'//导入子组件import Nav from "./nav.vue"//子组件通过inject注入父组件提供的 响应式数据const user = inject("provideUser")console.log("provideUser:",user.value)//provide用于父组件将 数据 提供给所有子组件provide("provideUrl","dengruicode.com")
</script><template><h3>header.vue-Middle组件</h3><!-- 子组件 --><Nav/>
</template><style scoped></style>nav.vue<script setup>//子组件import { inject } from 'vue'//子组件通过inject注入父组件提供的 数据const web = inject("provideWeb")console.log("provideWeb:",web)const url = inject("provideUrl")console.log("provideUrl:",url)//子组件通过inject注入父组件提供的 函数const funcUserAdd = inject("provideFuncUserAdd")console.log("provideFuncUserAdd:",funcUserAdd)
</script><template><h3>nav.vue-Bottom组件</h3><button @click="funcUserAdd">添加用户</button>
</template><style scoped></style>

7.匿名插槽和具名插槽

插槽(slot)是指可以在父组件内自定义模板片段,在子组件中可以将定义的模板片段插入到子组件的特定位置App.vue<script setup>//导入子组件import Header from "./components/header.vue"import Footer from "./components/footer.vue"
</script><template><h3>App.vue</h3><!-- <Header/> --><!-- 匿名插槽 --><Header><a href="http://dengruicode.com">邓瑞编程</a></Header><!-- 具名插槽 --><Footer><template v-slot:url><a href="http://www.dengruicode.com">网址</a></template><!-- v-slot:user 简写 #user --><template #user>1000</template></Footer></template><style scoped></style>header.vue<script setup></script><template><h3>header.vue - 子组件</h3><!-- 匿名插槽 --><slot/>
</template><style scoped></style>footer.vue<script setup></script><template><h3>footer.vue - 子组件</h3><!-- 具名插槽 --><slot name="url" /><slot name="user" />
</template><style scoped></style>

8.作用域插槽


作用域插槽子组件向父组件传递数据,并在父组件定义的模板中渲染App.vue<script setup>//导入子组件import Header from "./components/header.vue"import Footer from "./components/footer.vue"
</script><template><h3>App.vue</h3><!-- <Header/> --><!-- 匿名插槽 --><Header><a href="http://dengruicode.com">邓瑞编程</a></Header><!-- 具名插槽 --><Footer><template v-slot:url><a href="http://www.dengruicode.com">网址</a></template><!--v-slot:user 简写 #user作用域插槽子组件将url和title数据传递给 name="user" 的插槽,父组件通过 #user="data" 来接收这些数据<template #user="data">1000 {{ data.url }} {{ data.title }}</template>--><!-- 解构 --><template #user="{url,title}">1000 {{ url }} {{ title }}</template></Footer></template><style scoped></style>header.vue<script setup></script><template><h3>header.vue - 子组件</h3><!-- 匿名插槽 --><slot/>
</template><style scoped></style>footer.vue<script setup></script><template><h3>footer.vue - 子组件</h3><!-- 具名插槽 --><slot name="url" /><slot name="user" url="dengruicode.com" title="邓瑞编程" />
</template><style scoped></style>

9.生命周期函数

生命周期函数是组件实例从创建到销毁过程中不同时间点自动调用的函数挂载阶段onBeforeMount在组件实例即将被挂载到DOM树之前调用此时模板还未编译或渲染到DOM,通常用于执行初始化操作,如:获取异步数据、设置初始属性值等onMounted在组件成功挂载到DOM并完成首次渲染后调用此时可以访问和操作DOM元素,并执行与页面交互相关的逻辑更新阶段onBeforeUpdate (由于响应式数据变化)在组件更新之前即将重新渲染时调用可以根据新的参数判断是否需要进行特殊处理,甚至可以选择阻止此次更新过程onUpdated在组件完成更新并重新渲染后调用可以基于新的渲染结果处理更新后的数据卸载阶段onBeforeUnmount在组件从DOM中销毁之前调用用于释放资源,如:清理计时器、解绑事件监听器等onUnmounted在组件已经从DOM中移除并销毁后调用确保组件所占用的所有资源都被正确释放错误处理onErrorCaptured在捕获到组件中的错误时调用用于处理错误,如:记录错误日志等注组件挂载的过程模板编译将组件的模板转换为JS代码渲染在模板编译后生成的JS代码渲染到页面上,生成虚拟DOM挂载在渲染完成后将虚拟DOM挂载到真实的DOM树上,使其在页面上显示出来<script setup>import { onMounted, onUpdated, ref } from 'vue'//在组件成功挂载到DOM并完成首次渲染后调用onMounted(() => {console.log("onMounted")})//在组件更新之后调用onUpdated(() => {console.log("onUpdated:",user.value)})const user = ref(0)console.log("user:",user.value)
</script><template><h3>App.vue</h3>{{ user }}<button @click="user++">添加用户</button>
</template><style scoped></style>

10.toRef和toRefs

<script setup>import { reactive, toRef, toRefs } from 'vue'/*let {name,url} = reactive({name:"邓瑞编程",url:"dengruicode.com"})*/let web = reactive({name:"邓瑞编程",url:"dengruicode.com"})//toRefs将一个响应式对象的所有属性转换为ref对象//let {name,url} = toRefs(web)//toRef将一个响应式对象的某个属性转换为ref变量let url = toRef(web, "url")const setUrl = () => {console.log(url)url.value = "www.dengruicode.com"}
</script><template>{{ url }}<button @click="setUrl">设置网址</button>
</template><style scoped></style>

Vue3 快速入门4-Pinia

1.Pinia 简介

  Pinia是一个轻量级的状态管理库Pinia官网https://pinia.vuejs.org/zh状态管理库是用于管理应用程序全局状态的工具以登录为例:使用Pinia创建一个userStore来集中管理用户的登录状态和过期时间当用户登录成功时:设置userStore中用户的登录状态为已登录,并设置过期时间当用户退出登录时:修改userStore中用户的登录状态为未登录,并删除过期时间Pinia 和 组件通信 的区别虽然Vue提供的父传子、子传父以及跨组件通信也可以用于状态共享,但在大型项目中,随着组件数量的增加,会导致以下问题:1.组件之间传递大量的props,会使项目变得非常繁琐和难以维护2.非父子组件间过度依赖provide/inject,使状态散落在各个组件之间Pinia 可以解决以下问题:1.全局状态管理所有组件都可以访问和修改状态,而不用在每个组件内部进行状态管理2.简化组件之间的通信避免在组件之间传递大量的props3.状态持久化可以将应用程序的状态保存到本地存储中,在应用程序重启后会保留状态,对于登录等场景非常有用总的来说,Pinia可以处理大型项目中复杂的状态管理需求,而父传子、子传父以及跨组件通信,可以解决一些简单的状态传递问题,更适合小型项目Pinia 和 localStorage 的区别localStorageLocalStorage只能存储字符串类型的数据LocalStorage有大小限制,通常为5MB左右PiniaPinia可以存储任何类型的数据,包括对象、数组等Pinia没有大小限制,可以存储大量的数据总的来说,对于复杂的状态管理需求,使用Pinia是更好的选择,而对于简单的状态管理需求,使用localStorage是更简单的解决方案

2.安装 Pinia 以及定义和使用 Store

安装Pinianpm install piniamain.jsimport { createApp } from 'vue'//导入Pinia的createPinia方法,用于创建Pinia实例(状态管理库)
import { createPinia } from 'pinia'import App from './App.vue'//创建一个Pinia实例,用于在应用中集中管理状态(store)
const pinia = createPinia()//createApp(App).mount('#app')
const app = createApp(App)
app.use(pinia) //将Pinia实例注册到Vue应用中
app.mount('#app')web.jsimport { reactive, ref } from 'vue'
import { defineStore } from 'pinia'/*定义一个基于 Pinia 的 Store第1个参数 web 是 useWebStore 在应用中的唯一标识符(ID)第2个参数是 Setup函数 或 Option对象
*/
export const useWebStore = defineStore('web', () => {//定义一个响应式对象,存储网站信息const web = reactive({title: "邓瑞编程",url: "dengruicode.com"})//定义一个响应式引用,存储用户数const users = ref(1000)//定义方法const userAdd = () => {users.value++}return {web,users,userAdd}
})App.vue<script setup>import { useWebStore } from './stores/web.js'const webStore = useWebStore()console.log("webStore.web:",webStore.web)console.log("webStore.users:",webStore.users)
</script><template>{{ webStore.web.url }}{{ webStore.users }}<button @click="webStore.userAdd" >添加用户</button>
</template><style scoped></style>

3.Pinia 持久化存储插件

官网
https://prazdevs.github.io/pinia-plugin-persistedstate/zh
安装
npm i pinia-plugin-persistedstate
注
pinia持久化插件也是存储到localStorage中,
为什么不直接使用localStorage?
自动状态同步持久化插件自动将Pinia的状态存储到localStorage中,无需手动处理状态的读取和写入
易用性无需手动处理localStorage的键值对存储、数据转换等繁琐过程
与Vue组件状态紧密集成持久化插件与Vue组件的响应式数据完美结合当状态改变时,依赖这些状态的组件会自动更新视图与仅仅从localStorage中读取静态数据相比更加灵活和强大main.jsimport { createApp } from 'vue'//导入Pinia的createPinia方法,用于创建Pinia实例(状态管理库)
import { createPinia } from 'pinia'//从 pinia-plugin-persistedstate 模块中导入 piniaPluginPersistedstate
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'import App from './App.vue'//创建一个Pinia实例,用于在应用中集中管理状态(store)
const pinia = createPinia()//将插件添加到 pinia 实例上
pinia.use(piniaPluginPersistedstate)//createApp(App).mount('#app')
const app = createApp(App)
app.use(pinia) //将Pinia实例注册到Vue应用中
app.mount('#app')web.jsimport { reactive, ref } from 'vue'
import { defineStore } from 'pinia'/*定义一个基于 Pinia 的 Store第1个参数 web 是 useWebStore 在应用中的唯一标识符(ID)第2个参数是 Setup函数 或 Option对象
*/
export const useWebStore = defineStore('web', () => {//定义一个响应式对象,存储网站信息const web = reactive({title: "邓瑞编程",url: "dengruicode.com"})//定义一个响应式引用,存储用户数const users = ref(1000)//定义方法const userAdd = () => {users.value++}return {web,users,userAdd}
},
{//持久化存储到 localStorage 中persist: true
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.bcls.cn/kMhH/99.shtml

如若内容造成侵权/违法违规/事实不符,请联系编程老四网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

【自然语言处理】seq2seq模型—机器翻译

清华大学驭风计划课程链接 学堂在线 - 精品在线课程学习平台 (xuetangx.com) 代码和报告均为本人自己实现&#xff08;实验满分&#xff09;&#xff0c;只展示主要任务实验结果&#xff0c;如果需要详细的实验报告或者代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢…

DS:八大排序之归并排序、计数排序

创作不易&#xff0c;感谢三连支持&#xff01;&#xff01; 一、归并排序 1.1 思想 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide andConquer&#xff09;的一个非常典型的应用。将已有序的子…

并发编程-多线程并发特性

多线程并发的三个特性 原子性&#xff1a;即一个操作或多个操作&#xff0c;要么全部执行&#xff0c;要么就都不执。执行过程中&#xff0c;不能被打断有序性&#xff1a;程序代码按照先后顺序执行 为什么会出现无序问题呢&#xff1f;因为指令重排&#xff08;重排序是编译器…

openlayers地图点击标记点,弹出当前位置自定义弹窗(三)

1. 效果图 2. 代码 <template><div class"container"><div id"map" stylewidth: 100%; height: 100%;border: 5px solid #a4cdff;><div class"toolBox"><div class"messageBox" v-show"isShow&quo…

算法沉淀——BFS 解决最短路问题(leetcode真题剖析)

算法沉淀——BFS 解决最短路问题&#xff08;leetcode真题剖析&#xff09; 01.迷宫中离入口最近的出口02.最小基因变化03.单词接龙04.为高尔夫比赛砍树 BFS&#xff08;广度优先搜索&#xff09;是解决最短路径问题的一种常见算法。在这种情况下&#xff0c;我们通常使用BFS来…

【漏洞复现-通达OA】通达OA report_bi存在前台SQL注入漏洞

一、漏洞简介 通达OA(Office Anywhere网络智能办公系统)是由北京通达信科科技有限公司自主研发的协同办公自动化软件,是与中国企业管理实践相结合形成的综合管理办公平台。通达OA为各行业不同规模的众多用户提供信息化管理能力,包括流程审批、行政办公、日常事务、数据统计…

MySQL篇之SQL优化

一、表的设计优化 表的设计优化&#xff08;参考阿里开发手册《嵩山版》&#xff09;&#xff1a; 1. 比如设置合适的数值&#xff08;tinyint int bigint&#xff09;&#xff0c;要根据实际情况选择。 2. 比如设置合适的字符串类型&#xff08;char和varchar&#xff09…

MSS与cwnd的关系,rwnd又是什么?

cwnd初始状态是多少&#xff1f; 拥塞窗口&#xff08;cwnd&#xff09;的初始状态通常设为1&#xff08;MSS)&#xff0c;即cwnd1。 在TCP连接建立初期&#xff0c;为了谨慎地探测网络容量&#xff0c;拥塞窗口&#xff08;cwnd&#xff09;会被设置为一个较小的值&#xff…

详解tomcat中的jmx监控

目录 1.概述 2.如何开启tomcat的JMX 3.tomcat如何实现JMX的源码分析 1.概述 本文是博主JAVA监控技术系列文章的第二篇&#xff0c;前面一篇文章中我们介绍了JAVA监控技术的基石——jmx&#xff1a; 【JMX】JAVA监控的基石-CSDN博客 本文我们将从使用和源码实现两个方面聊…

【c++】list详细讲解

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟悉list库 > 毒鸡汤&#xff1a;你的脸上云淡…

【java苍穹外卖项目实战三】nginx反向代理和负载均衡

文章目录 1、nginx反向代理2、nginx 反向代理的好处3、nginx 反向代理的配置方式5、nginx 负载均衡的配置方式6、nginx 负载均衡策略 我们思考一个问题&#xff1a; 前端发送的请求&#xff0c;是如何请求到后端服务的&#xff1f; 前端请求地址&#xff1a;http://localhost/…

快速搭建PyTorch环境:Miniconda一步到位

快速搭建PyTorch环境&#xff1a;Miniconda一步到位 &#x1f335;文章目录&#x1f335; &#x1f333;一、为何选择Miniconda搭建PyTorch环境&#xff1f;&#x1f333;&#x1f333;二、Miniconda安装指南&#xff1a;轻松上手&#x1f333;&#x1f333;三、PyTorch与Minic…

MySQL篇----第十四篇

系列文章目录 文章目录 系列文章目录前言一、MySQL 数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化?二、锁的优化策略三、索引的底层实现原理和优化四、什么情况下设置了索引但无法使用前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽…

c++用户管理信息(单链表管理)

c用户管理信息---单链表管理 类示意图select类示意图cFile类示意图ListStu类示意图ClassStu示意图 项目源代码selectselect.hselect.cpp cFilecFile.hcFile.cpp ListStuListStu.hListStu.cpp ClassStuClassStu.hClassStu.cpp main 源码 类示意图 select类示意图 cFile类示意图…

ChatGPT的大致原理

国外有个博主写了一篇博文&#xff0c;名字叫TChatGPT: Explained to KidsQ」&#xff0c; 直译过来就是&#xff0c;给小孩子解释什么是ChatGPT。 因为现实是很多的小孩子已经可以用父母的手机版ChatGPT玩了 &#xff0c;ChatGPT几乎可以算得上无所不知&#xff0c;起码给小孩…

嵌入式I2C 信号线为何加上拉电阻(图文并茂)

IIC 是一个两线串行通信总线&#xff0c;包含一个 SCL 信号和 SDA 信号&#xff0c;SCL 是时钟信号&#xff0c;从主设备发出&#xff0c;SDA 是数据信号&#xff0c;是一个双向的&#xff0c;设备发送数据和接收数据都是通过 SDA 信号。 在设计 IIC 信号电路的时候我们会在 SC…

[ai笔记10] 关于sora火爆的反思

欢迎来到文思源想的ai空间&#xff0c;这是技术老兵重学ai以及成长思考的第10篇分享&#xff01; 最近sora还持续在技术圈、博客、抖音发酵&#xff0c;许多人都在纷纷发表对它的看法&#xff0c;这是一个既让人惊喜也感到焦虑的事件。openai从2023年开始&#xff0c;每隔几个…

django实现外键

一&#xff1a;介绍 在Django中&#xff0c;外键是通过在模型字段中使用ForeignKey来实现的。ForeignKey字段用于表示一个模型与另一个模型之间的多对一关系。这通常用于关联主键字段&#xff0c;以便在一个模型中引用另一个模型的相关记录。 下面是一个简单的例子&#xff0…

电商API接口|大数据关键技术之数据采集发展趋势

在大数据和人工智能时代&#xff0c;数据之于人工智能的重要性不言而喻。今天&#xff0c;让我们一起聊聊数据采集相关的发展趋势。 本文从电商API接口数据采集场景、数据采集系统、数据采集技术方面阐述数据采集的发展趋势。 01 数据采集场景的发展趋势 作为大数据和人工智…

适用于 Windows 的 12 个最佳 PDF 编辑器

PDF文档的普遍存在按理说&#xff0c;PDF文档的可读性和可移植性受到专业文档的青睐。 然而&#xff0c;PDF格式的可食用性是一大缺陷。幸运的是&#xff0c;各种 PDF 编辑工具和软件使 PDF 的编辑变得更加容易&#xff0c;这篇文章旨在帮助我们的读者找到其中最好的工具和软件…
推荐文章