--- title: Vue 學習 tags: vue --- > [中文文檔](https://v3.cn.vuejs.org/guide/introduction.html) > [CSS 函式庫 Bootstrap](https://bootstrap5.hexschool.com/) > [chrome 擴充](https://chrome.google.com/webstore/detail/vuejs-devtools/ljjemllljcmogpfapbkkighbhhppjdbg) ![](https://i.imgur.com/n5S2J9Z.png) ### VSCode 相關套件 - [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) - [Vue 官方提供的 Vue 整合插件](https://marketplace.visualstudio.com/items?itemName=octref.vetur) - [Vue 3 Snippets](https://marketplace.visualstudio.com/items?itemName=hollowtree.vue-snippets) --- ### 運作概念 **MVVM** 全名為 Model-View-ViewModel * M 代表 Model(存放資料) * V 代表 View(畫面顯示) * VM 稱作 ViewModel(資料與畫面互動) ![](https://i.imgur.com/9KLZNLk.png) ### createApp ```javascript <div id="app"> {{counter}} {{text}} </div> <script> Vue.createApp({ data() { return { counter: 5, text: '這是一段話', } } }).mount('#app') </script> ``` ![](https://i.imgur.com/NBR7ek9.png) ### 起手式 :::info 可輸入 `div.app` or `div#app` ::: ```javascript <div id="app"> {{ counter }} <button type="button" v-on:click="clickMe"> 按我 </button> </div> <script> const app = { // 資料 -> 函式 data(){ return{ counter: 0 } }, // 生命週期 -> 函式 created() { this.counter = 10 console.log(this); }, // 方法 -> 物件 methods: { clickMe() { console.log(1); this.counter = this.counter + 1 } }, } Vue.createApp(app).mount('#app') </script> ``` ![](https://i.imgur.com/nXPjXP3.png) ### 雙向綁定 ```javascript <div id="app"> <form> {{ temp }} <div class="mb-3"> <label for="productName" class="form-label">產品名稱</label> <input type="text" id="productName" class="form-control" v-model="temp.name"> </div> <div class="mb-3"> <!-- html 屬性 --> <img v-bind:src="temp.imageUrl" class="img-fluid" alt=""> <label for="productImage" class="form-label">產品圖片</label> <input type="text" id="productImage"class="form-control" v-model="temp.imageUrl"> </div> <button type="button" class="btn btn-secondary" v-on:click="confirmEdit">更新</button> </form> </div> <script> const App = { data() { return { temp: { name: '', imageUrl: 'https://images.unsplash.com/photo-1602526430780-782d6b1783fa?ixid=MXwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80' } } }, methods: { confirmEdit(){ console.log(this.temp) } }, }; Vue.createApp(App).mount('#app'); </script> ``` ### 資料操作 ![](https://i.imgur.com/zu2adKJ.png) ```javascript <div id="app"> <form> <div class="mb-3"> <label for="productName" class="form-label">產品名稱</label> <input type="text" id="productName" class="form-control" v-model="temp.name"> </div> <div class="mb-3"> <img :src="temp.imageUrl" class="img-fluid d-block" alt="" width="300"> <label for="productImage" class="form-label">產品圖片</label> <input type="text" id="productImage" class="form-control" v-model="temp.imageUrl"> </div> <button type="button" class="btn btn-secondary" v-on:click="confirmEdit">更新</button> </form> </div> <script> const products = [{ id: '1', imageUrl: 'https://images.unsplash.com/photo-1516906571665-49af58989c4e?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=300&q=80', name: 'MacBook Pro', onStock: false, },{ id: '2', imageUrl: 'https://images.unsplash.com/photo-1512499617640-c74ae3a79d37?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=300&q=80', name: 'iPhone', onStock: false, }]; const App = { data() { return { products: [], temp: { name: '卡斯伯', imageUrl: 'https://images.unsplash.com/photo-1602526430780-782d6b1783fa?ixid=MXwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80' } } }, methods: { confirmEdit() { this.temp.id = new Date().getTime();//unix timestamp this.temp.onStock = false; console.log(this.temp); this.products.push(this.temp); // 把 temp 加到 products this.temp = {}; } }, created() { this.products = products; }, }; Vue.createApp(App).mount('#app'); </script> ``` ### 多筆資料渲染 ![](https://i.imgur.com/uo6M0na.png) ```javascript <tr v-for="item in products" :key="item.id" v-bind:class="{'table-success': item.onStock}"> <td> {{ item.name }} </td> <td> <img v-bind:src="item.imageUrl" alt=""> </td> <td> <input type="checkbox" v-model='item.onStock'> <!-- {{ item.onStock }} --> </td> <td> <button type="button" class="btn btn-outline-primary"> 編輯 </button> </td> </tr> ``` ### 指令 ![](https://i.imgur.com/Mj65NRo.png) #### `v-for` ```javascript <ul> <li v-for="(item, key) in products"> {{key+1}} . {{item.name}}/{{item.price}}元</li> </ul> ``` ```javascript products: [ { name: '蛋餅', price: 30, vegan: false }, { name: '飯糰', price: 35, vegan: false }, { name: '小籠包', price: 60, vegan: false }, { name: '蘿蔔糕', price: 30, vegan: true }, ], ``` ![](https://i.imgur.com/fOPfPKm.png) ```javascript <ul> <li v-for="(item, key) in productsObj"> {{key}} . {{item.name}}/{{item.price}}</li> </ul> ``` ```javascript productsObj: { chineseOmelette: { name: '蛋餅', price: 30, vegan: false }, riceBall: { name: '飯糰', price: 35, vegan: false }, soupDumpling: { name: '小籠包', price: 60, vegan: false }, radishCake: { name: '蘿蔔糕', price: 30, vegan: true } }, ``` ![](https://i.imgur.com/r1p0TPq.png)