Vue3核心語法基礎

一、為什么要學 Composition API?

在以前我們寫代碼用Vue2寫:

export default {data() {return { count: 0, msg: 'hello' }},methods: {add() { this.count++ }},computed: {double() { return this.count * 2 }}
}

很明顯?

一個功能被拆成三塊:datamethodscomputed,找起來麻煩,改起來更麻煩。

Vue3 提出了 Composition API,把同一功能的代碼用函數包在一起,就像把襪子卷成球——整整齊齊不丟單只!

二、舞臺:setup 函數

1. setup 是什么?

  • 舞臺:所有 Composition API 都要在 setup() 里表演。

  • 時機:組件創建前執行,比任何生命周期都早。

  • 注意:里面訪問 this 會得到 undefined(因為組件實例還沒出生呢)。

<template><p>{{ name }}</p><button @click="changeName">改名</button>
</template><script>
export default {setup() {let name = '張三'function changeName() {name = '李四' // 頁面不會變!因為 name 不是響應式console.log(name)}return { name, changeName } // 暴露給模板用}
}
</script>

我說白了:setup?是 Vue 3 中一個新概念,它就像是組件的"控制中心"或"大腦"。讓我用大白話給你解釋:?

想象一下你要組裝一個玩具:

  • setup?就像是打開工具箱的步驟

  • 在這個工具箱里,你準備好所有零件(數據、方法、計算屬性等)

  • 然后你告訴 Vue:"這些就是我要在組件里使用的所有東西"

三、讓數據活起來:ref 與 reactive

讓數據活起來是啥意思呢?

讓我們來試試:

let A = 1
import { ref } from 'vue'let B = ref(1)

這兩有什么區別呢?

第一個是一個"死"數據,是非響應式的數據

第二個是可以發生更改的響應式數據

1. ref:基本類型的響應式法寶

  • 語法let xxx = ref(初始值)

  • 規矩:在 JS 里改要加 .value,模板里直接用。

<script setup>
import { ref } from 'vue'let age = ref(18)function addAge() {age.value++ // JS 里要加 .value
}
</script><template><p>年齡:{{ age }}</p> <!-- 模板里不用 .value --><button @click="addAge">+1</button>
</template>

2. reactive:對象類型的響應式法寶

  • 語法let obj = reactive({...})

  • 深度響應:對象里隨便嵌套多少層,都能追蹤變化。

    <script setup>
    import { reactive } from 'vue'let car = reactive({ brand: '奔馳', price: 100 })function addPrice() {car.price += 10
    }
    </script><template><p>我的{{ car.brand }}價值{{ car.price }}萬</p><button @click="addPrice">再漲10萬</button>
    </template>

    3. ref vs reactive 速記表

    場景推薦原因
    基本類型refreactive 會報警告
    簡單對象均可看個人喜好
    深層嵌套對象reactive寫起來更簡潔,無需層層.value

    四、語法糖?<script setup>:懶人必備

    每次寫 setup() { return {...} } 很煩?Vue3 提供語法糖:

<script setup>
// 這里面的代碼直接就是 setup 的內容,無需 return
import { ref } from 'vue'
const count = ref(0)
</script>

(還能更懶)再裝個插件 vite-plugin-vue-setup-extend,還能直接寫組件名:

<script setup name="UserCard">
// 組件名就叫 UserCard,省去寫 name 屬性
</script>

五、解構不丟響應式:toRefs & toRef

當你想從 reactive 對象中“摘”屬性出來用時,直接解構會丟失響應式,就像把耳機線從卷線盒里抽出來——全亂了!

toRefs / toRef 解決:

哈這個時候就會有同學說,toRef與toRefs的區別是什么呢?,其實最大的區別就是有沒有s

toRef?的作用

  • 功能:將響應式對象(reactive 創建的對象)中的單個屬性轉換為一個響應式的 ref 對象。

toRefs?的作用

  • 功能:將響應式對象(reactive 創建的對象)的所有屬性批量轉換為 ref 對象,并包裝成一個普通對象(每個屬性都是對應的 ref)。
import { reactive, toRefs } from 'vue'const user = reactive({name: 'Alice',age: 20
})// 將 user 的所有屬性轉換為 ref 并包裝成普通對象
const refs = toRefs(user)
// refs 結構:{ name: Ref, age: Ref }// 解構后仍保持響應性
const { name, age } = refs// 修改 ref 會同步影響原對象
name.value = 'Bob'
console.log(user.name) // 輸出:Bob// 修改原對象也會同步影響 ref
user.age = 21
console.log(age.value) // 輸出:21

?????????好啦,到這里已經將最基礎的幾個用法,和框架已經搭好了,所以也來用兩個練習來鞏固一下下

六、實戰小案例:待辦事項

需求:添加、刪除、標記完成,并統計完成數量。

<script setup>
import { ref, reactive, computed } from 'vue'// 1. 數據
const todos = reactive([])
const input = ref('')// 2. 計算屬性
const doneCount = computed(() => todos.filter(t => t.done).length)// 3. 方法
function addTodo() {if (!input.value.trim()) returntodos.push({ id: Date.now(), text: input.value, done: false })input.value = ''
}function toggle(todo) {todo.done = !todo.done
}function delTodo(id) {const index = todos.findIndex(t => t.id === id)todos.splice(index, 1)
}
</script><template><h2>待辦清單</h2><input v-model="input" @keyup.enter="addTodo" placeholder="輸入后敲回車" /><ul><li v-for="t in todos" :key="t.id"><input type="checkbox" v-model="t.done" /><span :class="{ done: t.done }">{{ t.text }}</span><button @click="delTodo(t.id)">刪除</button></li></ul><p>已完成:{{ doneCount }} / {{ todos.length }}</p>
</template><style>
.done { text-decoration: line-through; color: gray; }
</style>

這里面有一個用法沒講,就是computed,它的作用也很簡單,就是對數據的自動更新(當數據變化的時候,它這個函數就會觸發,讓數據發生更新)?

七、課后作業(動手才能真會)

  1. 個人資料卡
    <script setup> 做一個可編輯的“姓名、年齡、郵箱、簡介”卡片,要求支持新增、修改、刪除。

  2. 購物車 2.0
    在上文購物車案例基礎上,增加:

    • 商品數量加減

    • 優惠券打 9 折

    • 按分類篩

因為我們現在是比較基礎的,所以我們最好是邏輯清晰,將這些都理解

作業一:

思路:

卡片:很簡單,用一個div盒子裝著,將里面的元素全部寫在盒子里面,再將里面的元素居中,樣式肯定就不會差。

可編輯的“姓名、年齡、郵箱、簡介”:用input將他們顯示出來,但是我們要獲取輸入框里面的元素,這個時候我們就需要v-model進行雙向綁定

新增、修改、刪除.:這些毫無疑問肯定是一堆按鈕,所以我們需要寫點擊按鈕,里面函數用一些的方法進行這些操作

最后其實需要顯示出來的,將原本一開始的元素顯示出來,后面增加的元素也需要事實顯示出來。

代碼(簡陋版)

<script setup lang="ts">
// 練習1:創建一個個人資料編輯組件,要求使用setup語法糖,
// 包含姓名、年齡、郵箱、個人簡介等字段,實現數據的增刪改查功能。
import {reactive} from "vue";
import { ref } from 'vue'interface Profile {id: numbername: stringage: numberemail: stringintro: string
}// 資料列表
const profiles = ref<Profile[]>([])// 表單數據
const form = ref<Profile>({id: Date.now(),name: '',age: 0,email: '',intro: ''
})function text() {console.log(profiles)console.log("=================")console.log(form)
}const isEdit = ref(false)
let editIndex = -1function resetForm() {form.value = {id: Date.now(),// id: Date.now() 表示用當前的時間戳(即自1970年1月1日以來的毫秒數)來生成一個唯一的數字,作為這個新表單的唯一標識。name: '',age: 0,email: '',intro: ''}isEdit.value = falseeditIndex = -1
}// ... 是擴展運算符,用于“展開”對象里的所有屬性。
// { ...form.value } 表示“復制 form.value 里的所有屬性到一個新對象”。
// 常用于【對象淺拷貝】、【合并屬性】等操作。
// 等價于
// const obj = {
//   name: form.value.name,
//   age: form.value.age,
//   // ...其他所有屬性
// }
// 但用 ...form.value 寫法更簡潔、更靈活。// 新增或保存編輯
function handleSubmit() {if (isEdit.value && editIndex !== -1) {profiles.value[editIndex] = { ...form.value }} else {profiles.value.push({ ...form.value })}resetForm()
}// 編輯
function editProfile(idx: number) {const item = profiles.value[idx]form.value = { ...item }isEdit.value = trueeditIndex = idx
}// 刪除
function deleteProfile(idx: number) {profiles.value.splice(idx, 1)if (isEdit.value && editIndex === idx) {resetForm()}
}</script><template><button @click="text">檢查</button><div><h2>個人資料編輯</h2><form @submit.prevent="handleSubmit"><div><label>姓名:</label><input v-model="form.name" required /></div><div><label>年齡:</label><input v-model.number="form.age" type="number" required min="0" /></div><div><label>郵箱:</label><input v-model="form.email" type="email" required /></div><div><label>個人簡介:</label><textarea v-model="form.intro" required></textarea></div><button type="submit">{{ isEdit ? '保存修改' : '添加' }}</button><button v-if="isEdit" type="button" @click="resetForm">取消編輯</button></form><h3>資料列表</h3><table border="1" cellpadding="5"><thead><tr><th>姓名</th><th>年齡</th><th>郵箱</th><th>個人簡介</th><th>操作</th></tr></thead><tbody><tr v-for="(profile, idx) in profiles" :key="profile.id">
<!--          <td>{{ key }}</td>--><td>{{ profile.name }}</td><td>{{ profile.age }}</td><td>{{ profile.email }}</td><td>{{ profile.intro }}</td><td><button @click="editProfile(idx)">編輯</button><button @click="deleteProfile(idx)">刪除</button></td></tr></tbody></table></div></template><style scoped></style>
作業二:

接下來的購物車的思路:

其實完全就是名片作業的升級版而已,你將名片變成購物車,進行購物車的增加,刪除功能

新功能:進行購物車里面商品的價錢的總和,并且進行優惠價的計算

????????

<template><div class="shopping-cart"><h2>購物車(進階版)</h2><div class="category-filter"><span>分類:</span><buttonv-for="category in categories":key="category":class="{ active: selectedCategory === category }"@click="selectCategory(category)">{{ category }}</button></div><table class="cart-table"><thead><tr><th>商品</th><th>單價</th><th>數量</th><th>小計</th><th>操作</th></tr></thead><tbody><tr v-for="item in filteredCartItems" :key="item.id"><td>{{ item.name }} ({{ item.category }})</td><td>¥{{ item.price.toFixed(2) }}</td><td><button @click="decreaseQuantity(item)">-</button>{{ item.quantity }}<button @click="increaseQuantity(item)">+</button></td><td>¥{{ (item.price * item.quantity).toFixed(2) }}</td><td><button @click="removeItem(item)">刪除</button></td></tr></tbody></table><div class="coupon-section"><label for="coupon">優惠券:</label><select id="coupon" v-model="selectedCoupon"><option value="">請選擇</option><option v-for="coupon in coupons" :key="coupon.id" :value="coupon.code">{{ coupon.name }} ({{ coupon.discount }}% off)</option></select></div><div class="total">總計:¥{{ total.toFixed(2) }}</div></div>
</template><script>
export default {data() {return {cartItems: [{id: 1,name: "蘋果",category: "生鮮",price: 6.5,quantity: 3},{id: 2,name: "T恤",category: "服飾",price: 59,quantity: 1},{id: 3,name: "藍牙耳機",category: "數碼",price: 199,quantity: 1}],categories: ["All", "生鮮", "數碼", "服飾"],selectedCategory: "All",coupons: [{ id: 1, code: "COUPON1", name: "滿減券", discount: 10 },{ id: 2, code: "COUPON2", name: "折扣券", discount: 15 }],selectedCoupon: ""};},computed: {filteredCartItems() {if (this.selectedCategory === "All") {return this.cartItems;}return this.cartItems.filter(item => item.category === this.selectedCategory);},total() {return this.cartItems.reduce((acc, item) => acc + item.price * item.quantity, 0);}},methods: {selectCategory(category) {this.selectedCategory = category;},increaseQuantity(item) {item.quantity++;},decreaseQuantity(item) {if (item.quantity > 1) {item.quantity--;}},removeItem(item) {const index = this.cartItems.indexOf(item);if (index!== -1) {this.cartItems.splice(index, 1);}}}
};
</script><style scoped>
.shopping-cart {font-family: Arial, sans-serif;
}
.category-filter button {margin-right: 5px;padding: 5px 10px;cursor: pointer;
}
.category-filter button.active {background-color: #4CAF50;color: white;
}
.cart-table {border-collapse: collapse;width: 100%;margin: 20px 0;
}
.cart-table th,
.cart-table td {border: 1px solid #ddd;padding: 8px;text-align: left;
}
.cart-table button {padding: 2px 5px;cursor: pointer;
}
.coupon-section {margin: 10px 0;
}
.total {font-weight: bold;font-size: 1.2em;
}
</style>

基礎的語法講到這里就結束拉!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91645.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91645.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91645.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

FSMC的配置和應用

一、FSMC 簡介與工作原理FSMC&#xff08;Flexible Static Memory Controller&#xff09;是 STM32 微控制器中用于與外部靜態存儲器&#xff08;如 SRAM、PSRAM、NOR Flash、LCD 等&#xff09;進行通信的一個外設模塊。1、支持的設備類型&#xff1a;SRAM / PSRAMNOR FlashNA…

Linux I/O 系統調用完整對比分析

Linux I/O 系統調用完整對比分析 1. 概述 Linux 提供了豐富的 I/O 系統調用&#xff0c;每種都有其特定的用途和優勢。本文將詳細分析這些系統調用的特點、使用場景和性能特征。 2. 系統調用詳細對比 2.1 基本讀寫函數 pread/pwrite #include <unistd.h>// 位置指定…

TiDB集群部署

架構&#xff1a; tidb–3臺&#xff0c;pd–3臺&#xff0c;tikv–3臺 8c16g200g 1x2.2x.2x7.124 1x2.2x.2x7.148 1x2.2x.2x7.87 1x2.2x.2x7.93 1x2.2x.2x7.127 1x2.2x.2x7.104 pd-3臺 4c8g100g 1x2.2x.2x7.143 1x2.2x.2x7.132 1x2.2x.2x7.91 1、下載安裝包 #注&#xff1a;我…

C#中對于List的多種排序方式

在 C# 中給 List<AI> 排序&#xff0c;只要 明確排序規則&#xff08;比如按某個字段、某幾個字段、或外部規則&#xff09;&#xff0c;就能用下面幾種常見寫法。下面全部基于這個示例類&#xff1a;public class AI {public int country; // 國家編號public int pr…

Spring框架中Bean的生命周期:源碼解析與最佳實踐

第1章&#xff1a;Spring Bean生命周期概述1.1 什么是Spring Bean生命周期&#xff1f;定義&#xff1a;Spring Bean生命周期是指從Bean的創建、初始化、使用到銷毀的完整過程&#xff0c;由Spring容器嚴格管理 。核心思想是Spring容器通過IoC&#xff08;控制反轉&#xff09;…

【51單片機6位數碼管密碼鎖】2022-10-15

緣由六位密碼器設計連接LED-嵌入式-CSDN問答 矩陣51單片機密碼鎖,回復:https://bbs.csdn.net/topics/392713242_智者知已應修善業的博客-CSDN博客 #include "REG52.h" unsigned char code smgduan[]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x…

?我的第一個開源項目:躍動的心

還是一個編程初學者時&#xff0c;我懷著激動的心情完成了人生第一個開源項目——一個用HTML5 Canvas制作的動態跳動愛心效果。這個項目雖然簡單&#xff0c;卻讓我深刻體會到了開源分享的快樂和技術創造的魅力。 壹、項目靈感 這個項目的靈感來源于瀏覽網頁時&#xff0c;被各…

技術演進中的開發沉思-53 DELPHI VCL系列:windows的消息(下):TApplication窗體

今天我們梳理下關于TApplication的窗體消息下半部分的內容。前面也說過&#xff0c;在 Delphi 的世界里&#xff0c;TApplication 就像一位經驗豐富的總工程師&#xff0c;而主窗體則是它傾注心血打造的核心建筑。如果你第一次在實驗室里敲出 Delphi 代碼時&#xff0c;屏幕上彈…

cesium FBO(四)自定義相機渲染到Canvas(離屏渲染)

前面幾節的例子是將Cesium默認的相機渲染到紋理&#xff08;RTT&#xff09;或Canvas&#xff0c;這片文章講解如何將自定義的一個camera的畫面渲染到Canvas上&#xff0c;有了前面幾篇的基礎了&#xff0c;也能將自定義的畫面渲染紋理、也可以灰度處理&#xff0c;原理是一樣的…

雙機并聯無功環流抑制虛擬阻抗VSG控制【simulink仿真模型實現】

雙機并聯虛擬同步發電機&#xff08;VSG&#xff09;系統中&#xff0c;因線路阻抗不匹配及參數差異&#xff0c;易引發無功環流。本方案在傳統VSG控制基礎上&#xff0c;引入自適應虛擬阻抗環節。其核心在于&#xff1a;實時檢測兩機間無功環流分量&#xff0c;據此動態調節各…

python測試總結

測試題的基礎知識點總結 1.循環求和 for循環步長&#xff08;range(2,101,2)&#xff09; while循環條件判斷&#xff08;i%20&#xff09; 生成器表達式&#xff08;sum(i for i in range )&#xff09; 所以&#xff1a;sum(range(1,101,2))&#xff08;奇數和&#xff09;和…

識別和分類惡意軟件樣本的工具YARA

YARA 是一個用于識別和分類惡意軟件樣本的工具,廣泛應用于惡意軟件分析、威脅情報、入侵檢測等領域。它通過編寫規則(YARA Rules)來匹配文件中的特定字符串、十六進制模式、正則表達式等特征。 一、YARA 的基本使用方法 1. 安裝 YARA Linux(Ubuntu/Debian) sudo apt-ge…

GaussDB 約束的語法

1 約束的作用約束是作用于數據表中列上的規則&#xff0c;用于限制表中數據的類型。約束的存在保證了數據庫中數據的精確性和可靠性。約束有列級和表級之分&#xff0c;列級約束作用于單一的列&#xff0c;而表級約束作用于整張數據表。下面是 GaussDB SQL 中常用的約束。NOT …

SecurityContextHolder 管理安全上下文的核心組件詳解

SecurityContextHolder 管理安全上下文的核心組件詳解在 Spring Security 中&#xff0c;SecurityContextHolder 是??安全上下文&#xff08;Security Context&#xff09;的核心存儲容器??&#xff0c;其核心作用是??在當前線程中保存當前用戶的認證信息&#xff08;如用…

c++詳解系列(引用指針)

目錄 1.什么是引用 2.引用的定義 3.引用的特性 4.引用的使用 4.1引用傳參 4.2傳引用返回 5.const引用&#xff08;在引用的定義前用const修飾&#xff09; 5.1對于引用 5.2對于指針 6.引用&指針 總結 1.什么是引用 引用就是給變量起別名&#xff0c;一個變量可以…

深度學習loss總結(二)

對于目前深度學習主流任務學習,loss的設置至關重要。下面就不同任務的loss設置進行如下總結: (1)目標檢測 2D/3D目標檢測中的 Loss(損失函數)是訓練模型時優化目標的核心,通常包括位置、類別、尺寸、方向等多個方面。以下是目前 常見的 2D 和 3D 目標檢測 Loss 分類與…

【Linux網絡】netstat 的 -anptu 各個參數各自表示什么意思?

netstat 是一個網絡統計工具&#xff0c;它可以顯示網絡連接、路由表、接口統計、偽裝連接和多播成員資格。在 netstat 命令中&#xff0c;不同的參數可以用來定制輸出的內容。 你提到的 -anptu 參數組合各自的功能如下&#xff1a; -a (all): 顯示所有活動的連接和監聽端口。它…

[硬件電路-115]:模擬電路 - 信號處理電路 - 功能放大器工作分類、工作原理、常見芯片

功能放大器是以特定功能為核心的集成化放大電路&#xff0c;通過將運算放大器與外圍電阻、電容等元件集成在單一芯片中&#xff0c;實現標準化、高性能的信號放大功能。其核心優勢在于簡化設計流程、提升系統穩定性&#xff0c;并針對特定應用場景優化性能參數。以下從定義、分…

雙網卡UDP廣播通信機制詳解

UDP廣播通信機制詳解 一、通信流程分析 發送階段 通過Client.Bind(192.168.0.3, 60000)將UDP套接字綁定到指定網卡和端口設置RemoteHost "255.255.255.255"實現全網段廣播數據流向&#xff1a;192.168.0.3:60000 → 255.255.255.255:50000 接收階段 設備響應數據應返…

從遮擋難題到精準測量:激光頻率梳技術如何實現深孔 3D 輪廓的 2um 級重復精度?

一、深孔 3D 輪廓測量的遮擋困境深孔結構&#xff08;如航空發動機燃油噴嘴孔、模具冷卻孔&#xff09;因孔深大&#xff08;常超 100mm&#xff09;、深徑比高&#xff08;&#xff1e;10:1&#xff09;&#xff0c;其 3D 輪廓測量長期受限于光學遮擋難題。傳統光學測量技術&a…