---
tags: Vue,第一章
---

官方網站
https://cn.vuejs.org/
cdn引入
```
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
```
```javascript=
<!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">{{msg}}</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
msg: "你好",
},
});
</script>
</body>
</html>
```
# 基礎語法
## 插值表達式
一定是Vue實例有的資料
可以求值的代碼都能寫進插值表達式
語句不可以寫進插值表達式
if(){}
for(){}
while(){}
標籤屬性不能用插值表達式
`<a href="{{url}}">google</a>`
```javascript=
<!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">
<p>{{nickname}}</p>
<p>{{nickname.substring(2)}}</p>
<p>{{age}}</p>
<p>{{age >= 18 ? '成年' : '未成年'}}</p>
<p>{{friend.name}}---{{friend.introduce}}</p>
<a href="{{url}}">google</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
nickname: "紫陽道長",
age: 18,
msg: "你好",
friend: {
name: "張三",
introduce: "熱愛學習",
},
},
});
</script>
</body>
</html>
```
## F12檢查
```javascript=
<!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">{{msg}}{{count}}</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
msg: "你好",
count:100
},
});
</script>
</body>
</html>
```
F12主控台可以查看與修改Vue實例
查看app.msg
修改app.msg = '不好'
查看app.count
修改app.count++
切記不用加data了
### 插件
官方測試網站
https://play.vuejs.org/#eNo9jDsOwjAQRK+yuDEUENEiJxIdN6Bxg5INRPJnZa/TWL47S5BSvnkzU9Wd6LIWVDdl8pgWYsjIhQYbFk8xMVRIOEODOUUPWqraBhvGGDKDz2/of/6oH+hchGdMbjrokw2m+9/JkQCjJ/diFAIwn+tQ6zZuzXRCW7oEKgzr2ccJXW+VeKtEmW5fq/YFaYM9HQ==
必裝插件

## v-html
設置元素的innerHTML
```javascript=
<!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">
<div v-html="msg">我是看不見的喔</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
msg: "<h2>前端Vue</h2>",
},
});
</script>
</body>
</html>
```
## v-if和v-show
### v-show
v-show = '表達式'
表達式結果必為布林值
原理:切換display:none
### v-if
v-if = '表達式'
表達式結果必為布林值
原理:創建或移除元素節點
```javascript=
<!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">
<div v-show="isShow">我是show</div>
<div v-if="isShow">我是if</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
isShow: false
},
});
</script>
</body>
</html>
```
## v-else和v-else-if
標籤跟標籤一定要緊貼
不過中間可以寫注釋
```javascript=
<!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">
<p v-if="gender===1">性別男</p>
<!-- 我是注釋 -->
<p v-else>性別女</p>
<hr />
<p v-if="score>=90">A</p>
<p v-else-if="score>=70">B</p>
<p v-else-if="score>=60">C</p>
<p v-else>D</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
gender: 1,
score: 95,
},
});
</script>
</body>
</html>
```
## v-on基本
`v-on:click='count++'`
簡寫後
`@click='count++'`
```javascript=
<!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">
<button v-on:click="count--">-</button>
<span>{{count}}</span>
<button v-on:click="count++">+</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
count:100
},
});
</script>
</body>
</html>
```
## v-on函式
method中的函式
其this都指向app(實例對象)
```javascript=
<!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">
<button @click="isShow= !isShow">切換顯示隱藏</button>
<button @click="change">切換顯示隱藏</button>
<h1 v-show="isShow">黑馬程序員</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
isShow: true
},
methods: {
change() {
this.isShow = !this.isShow;
console.log(this === app);
}
}
});
</script>
</body>
</html>
```
### ES6函式簡寫
```javascript=
<!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>
<script>
obj = {
fun1:function(){
console.log(111);
},
fun2(){
console.log(222);
}
};
obj.fun1();
obj.fun2();
</script>
</body>
</html>
```
## v-on傳參
`@click="buy(5)"`小括號不是調用函數,只是綁定事件實參而已
```javascript=
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.box {
width: 200px;
height: 100px;
border: 2px solid black;
text-align: center;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="app">
<div class="box">
<h3>小黑自動售貨機</h3>
<button @click="buy(5)">可樂5元</button>
<button @click="buy(10)">咖啡10元</button>
</div>
<p>銀行卡餘額:{{money}}元</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
money: 100
},
methods: {
buy(price) {
this.money > 0 ? (this.money -= price) : (this.money = 0);
}
}
});
</script>
</body>
</html>
```
## v-bind
`v-bind:src="imgUrl"`
簡寫後
`:src="imgUrl"`
```javascript=
<!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">
<img v-bind:src="imgUrl" :title="msg">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
imgUrl: "https://picsum.photos/200",
msg: "我是假圖喔",
},
});
</script>
</body>
</html>
```
## 小案例-切換圖片
```javascript=
<!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">
<button v-show="index>0" @click="index--">上一頁</button>
<div>
<img :src="list[index]" />
</div>
<button v-show="index<list.length-1" @click="index++">下一頁</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
index: 0,
list: [
"https://picsum.photos/100",
"https://picsum.photos/200",
"https://picsum.photos/300",
"https://picsum.photos/400",
"https://picsum.photos/500",
"https://picsum.photos/600",
],
},
});
</script>
</body>
</html>
```
## v-for
```javascript=
<!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">
<h3>小黑水果店</h3>
<ul>
<li v-for="(item,index) in list">{{item}}---{{index}}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
list: ["蘋果", "芭樂", "香蕉", "橘子"],
},
});
</script>
</body>
</html>
```
### v-for不用數組
```htmlmixed=
<ul>
<子組件 v-for="item in 4" :key="item"></子組件>
</ul>
```
## 小案例-小黑書架
```javascript=
<!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">
<h3>小黑的書架</h3>
<ul>
<li v-for="item in bookList">
<span>{{item.name}}</span>
<span>{{item.author}}</span>
<button @click="del(item.id)">刪除</button>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
bookList: [
{
id: 1,
name: "《紅樓夢》",
author: "曹雪芹",
},
{
id: 2,
name: "《西遊記》",
author: "吳承恩",
},
{
id: 3,
name: "《水滸傳》",
author: "施耐庵",
},
{
id: 4,
name: "《三國演義》",
author: "羅貫中",
},
],
},
methods: {
del(id) {
// console.log("我要刪除", id);
// const index = this.bookList.findIndex((item) => item.id === id);
// this.bookList.splice(index, 1);
// 更牛逼的方法
this.bookList = this.bookList.filter((item) => item.id !== id);
},
},
});
</script>
</body>
</html>
```
## v-for之key
### 不使用key
Vue不會輕易刪除DOM元素
v-for默認複用策略:
單前刪除一個元素後
Vue實際上是刪除最後一個元素
裡面內容平移
以複用現存li
...
測試項目
ul li:first-child 不會砍掉
input type="checkbox" 不會砍掉
```javascript=
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
ul li:first-child {
background-color: pink;
}
</style>
</head>
<body>
<div id="app">
<h3>小黑的書架</h3>
<ul>
<li v-for="item in bookList">
<input type="checkbox" />
<span>{{item.name}}</span>
<span>{{item.author}}</span>
<button @click="del(item.id)">刪除</button>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
bookList: [
{
id: 1,
name: "《紅樓夢》",
author: "曹雪芹",
},
{
id: 2,
name: "《西遊記》",
author: "吳承恩",
},
{
id: 3,
name: "《水滸傳》",
author: "施耐庵",
},
{
id: 4,
name: "《三國演義》",
author: "羅貫中",
},
],
},
methods: {
del(id) {
// console.log("我要刪除", id);
// const index = this.bookList.findIndex((item) => item.id === id);
// this.bookList.splice(index, 1);
// 更牛逼的方法
this.bookList = this.bookList.filter((item) => item.id !== id);
},
},
});
</script>
</body>
</html>
```
### 使用key
key一般常用唯一標誌符:id
不推薦使用index
key的設置要求:
1.一定要在當前v-for中唯一
2.必須是string或number
3.通常要配v-bind
...
測試項目
ul li:first-child 不會砍掉
input type="checkbox" 砍掉
```javascript=
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
ul li:first-child {
background-color: pink;
}
</style>
</head>
<body>
<div id="app">
<h3>小黑的書架</h3>
<ul>
<li v-for="item in bookList" :key="item.id">
<input type="checkbox" />
<span>{{item.name}}</span>
<span>{{item.author}}</span>
<button @click="del(item.id)">刪除</button>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
bookList: [
{
id: 1,
name: "《紅樓夢》",
author: "曹雪芹",
},
{
id: 2,
name: "《西遊記》",
author: "吳承恩",
},
{
id: 3,
name: "《水滸傳》",
author: "施耐庵",
},
{
id: 4,
name: "《三國演義》",
author: "羅貫中",
},
],
},
methods: {
del(id) {
// console.log("我要刪除", id);
// const index = this.bookList.findIndex((item) => item.id === id);
// this.bookList.splice(index, 1);
// 更牛逼的方法
this.bookList = this.bookList.filter((item) => item.id !== id);
},
},
});
</script>
</body>
</html>
```
## v-model

```javascript=
<!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">
帳戶: <input type="text" v-model="username" /><br /><br />
密碼: <input type="password" v-model="password" /><br /><br />
<button @click="login">登錄</button>
<button @click="reset">重置</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
username: "",
password: "",
},
methods: {
login() {
console.log(this.username, this.password);
},
reset() {
this.username = "";
this.password = "";
},
},
});
</script>
</body>
</html>
```
# 綜合案例-小黑記事本
```javascript=
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./p018.css" />
<title>小黑記事本</title>
</head>
<body>
<!-- 主區域 -->
<section id="app">
<!-- 輸入框 -->
<header>
<h1 class="title">小黑記事本</h1>
<div class="input">
<input class="mission" placeholder="請輸入任務" v-model="taskName" />
<button class="btn-big" @click="add">添加任務</button>
</div>
</header>
<!-- 列表區域 -->
<section>
<ul>
<li v-for="(item,index) in list" :key="item.id">
<div>
<span>{{index+1}}.</span><label for="">{{item.name}}</label
><button class="x" @click="del(item.id)"></button>
</div>
</li>
</ul>
</section>
<!-- 統計和清空 -->
<footer v-show="list.length>0">
<!-- 統計 -->
<span>合計:<strong>{{list.length}}</strong></span>
<!-- 清空 -->
<button @click="clear">清空任務</button>
</footer>
</section>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
list: [
{ id: 1, name: "跑步一公里" },
{ id: 2, name: "打球一小時" },
{ id: 3, name: "游泳100米" },
],
taskName: "",
},
methods: {
del(id) {
this.list = this.list.filter((item) => {
return item.id !== id;
});
},
add() {
if (this.taskName.trim() === "") {
return alert("請輸入任務名稱");
}
this.list.unshift({
id: +new Date(),
name: this.taskName,
});
this.taskName = "";
},
clear() {
this.list = [];
},
},
});
</script>
</body>
</html>
```
```css=
/* 全局 */
* {
list-style: none;
}
body {
background-color: #f5f5f5;
}
#app {
display: block;
width: 1000px;
height: 1000px;
margin: 100px auto;
text-align: center;
}
/* 輸入框 */
.title {
color: red;
font-size: 50px;
}
.input {
width: 240px;
border: 1px solid #ff5809;
margin: 0 auto;
display: flex;
justify-content: center;
}
.mission {
width: 160px;
height: 40px;
border: none;
}
.btn-big {
width: 80px;
height: 42px;
border: none;
background-color: #ff5809;
}
/* 列表區域 */
section ul li:hover .x::before {
content: "x";
}
.x{
border: none;
}
```