天天看點

Vue3 基礎Vue3 基礎

Vue3 基礎

概述

Vue (發音為 /vjuː/,類似 view) 是一款用于建構使用者界面的 JavaScript 架構。它基于标準 HTML、CSS 和 JavaScript 建構,并提供了一套聲明式的、元件化的程式設計模型,幫助你高效地開發使用者界面。無論是簡單還是複雜的界面,Vue 都可以勝任。

Vue 的兩個核心功能:

  • 聲明式渲染:Vue 基于标準 HTML 拓展了一套模闆文法,使得我們可以聲明式地描述最終輸出的 HTML 和 JavaScript 狀态之間的關系。
  • 響應性:Vue 會自動跟蹤 JavaScript 狀态并在其發生變化時響應式地更新 DOM。

Vue3官方文檔

Vite官方文檔

安裝Vue

一、使用CDN

<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
           

二、npm安裝

npm init [email protected]
           

三、下載下傳JavaScript檔案自行托管

使用JS的方式引入Vue

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue3簡單使用</title>
    <script src="./vue3.js"></script>
</head>

<body>
    <div id="counter">
        <p>{{uname}}</p>
        <p>{{age}}</p>
    </div>

    <script>
        // 配置對象
        const counter = {
            data: function () {
                return {
                    uname: "小明",
                    age: 0
                }
            }
        };

        // 使用createApp函數建立一個應用執行個體
        // 傳入配置對象
        let app = Vue.createApp(counter)
            // 應用執行個體必須調用mount函數,挂載後才會渲染出來
            .mount("#counter");

        //資料雙向綁定
        app.age = 18;
    </script>
</body>

</html>
           

使用vite

簡介

Vite是要給web開發建構工具,由于其原生ES子產品導入方式,可以實作閃電般的冷伺服器啟動。

使用vite搭建項目

npm create [email protected]
           

或者:

npm create [email protected] my-vue-app -- --template vue
           

接着依次執行指令啟動vue項目:

cd my-vue-app
npm install
npm run dev
           

模闆文法

Vue 使用一種基于 HTML 的模闆文法,使我們能夠聲明式地将其元件執行個體的資料綁定到呈現的 DOM 上。所有的 Vue 模闆都是文法層面合法的 HTML,可以被符合規範的浏覽器和 HTML 解析器解析。

在底層機制中,Vue 會将模闆編譯成高度優化的 JavaScript 代碼。結合響應式系統,當應用狀态變更時,Vue 能夠智能地推導出需要重新渲染的元件的最少數量,并應用最少的 DOM 操作。

基本使用

<script>
export default {
    data() {
        return {
            name: "小明123",
            age: 18,
            num: 0,
            rawHtml: "<h2 style='color:red;'>hello msg</h2>",
            myid: "id01",
            isBtnDisabled: true,
            objAttrs: {
                id: "id01",
                class: "box"
            },
            imgUrl: "https://cn.vitejs.dev/logo-with-shadow.png",
            attributeName: "id",
            mouseEvent: "click",
        }
    },
    methods: {
        changeNum() {
            this.num++;
        },
        changeColor() {
            this.id = "id01";
        },
        alertMsg() {
            alert("hello world");
        }
    }
}
</script>

<template>
    <!-- 文本插值 -->
    <p>姓名:{{ name }}</p>
    <p>年齡:{{ age }}</p>
    <p>數量:{{ num }}</p>

    <!-- 僅修改一次 -->
    <p v-once>數量:{{ num }}</p>
    <button @click="changeNum">修改num</button>

    <!-- 使用html -->
    <p v-html="rawHtml"></p>

    <!-- 屬性綁定 -->
    <p v-bind:id="myid">v-bind</p>
    <!-- v-bind簡寫 -->
    <p :id="myid">v-bind2</p>
    <!-- 布爾類型 -->
    <button :disabled="isBtnDisabled">v-bind2</button><br>
    <!-- 綁定多個屬性 -->
    <p v-bind="objAttrs">hello world</p>

    <!-- 動态參數 -->
    <p v-bind:[attributeName]="myid">動态屬性1</p>
    <img v-bind:src="imgUrl" style="width: 50px;">
    <!-- 簡寫 -->
    <p :[attributeName]="myid">動态屬性2</p>
    <button @[mouseEvent]="attributeName = 'class'">動态事件</button>
    <button @click="mouseEvent = 'mouseover'">改變事件</button><br>

    <!-- 點選事件 -->
    <button v-on:click="changeColor">修改顔色</button>
    <!-- 簡寫 -->
    <button @click="changeColor">修改顔色</button><br>

    <!-- 使用JavaScript表達式 -->
    <p>{{ num + 1 }}</p>
    <p>{{ name.split("").reverse().join("") }}</p>
</template>

<style>
#id01 {
    color: red;
}

#id02 {
    color: blue;
}

.id01 {
    color: green;
}

.id02 {
    color: yellowgreen;
}

.active {
    color: red;
}

.box {
    border: 1px dashed red;
}
</style>
           

條件渲染

<script>
    export default {
        data() {
            return {
                age: 68,
                isShow: true
            }
        }
    }
</script>

<template>
<!-- v-if條件渲染 -->
<p v-if="age < 18">未成年人</p>
<p v-if="age >= 18 && age < 60">年輕人</p>
<p v-else>老人</p>

<!-- v-show,本質是display:none; -->
<p v-show="isShow">
    hello template
    </p>
</template>
           
  • v-if

    :會根據條件進行渲染,切換時元素會被銷毀或重建,是以切換開銷大。
  • v-for

    :本質是通過

    display

    進行顯示和隐藏。

清單渲染

<script>
    export default {
        data() {
            return {
                userList: [
                    { name: "張三", age: 19, address: "北京" },
                    { name: "李四", age: 29, address: "上海" },
                    { name: "王五", age: 39, address: "廣州" }
                ],
                userInfo: {
                    name: "小白",
                    title: "頂級作者",
                    bookName: "西遊記"
                }
            }
        }
    }
</script>

<template>   
    <!-- v-for周遊數組 -->
    <ul>
        <li v-for="(item, index) in userList">
            編号:{{ index }} 姓名:{{ item.name }} 年齡:{{ item.age }} 位址:{{ item.address }}
        </li>
    </ul>
    <ul>
        <li v-for="({ name, age, address }, index) in userList">
            編号:{{ index }} 姓名:{{ name }} 年齡:{{ age }} 位址:{{ address }}
        </li>
    </ul>

    <!-- v-for周遊對象 -->
    <ul>
        <li v-for="(value, key) in userInfo">
            {{ key }} : {{ value }}
        </li>
    </ul>
</template>
           

通過key管理狀态

Vue 預設按照“就地更新”的政策來更新通過

v-for

渲染的元素清單。當資料項的順序改變時,Vue 不會随之移動 DOM 元素的順序,而是就地更新每個元素,確定它們在原本指定的索引位置上渲染。

預設模式是高效的,但隻适用于清單渲染輸出的結果不依賴子元件狀态或者臨時 DOM 狀态 (例如表單輸入值) 的情況。

Vue3 基礎Vue3 基礎

為了給 Vue 一個提示,以便它可以跟蹤每個節點的辨別,進而重用和重新排序現有的元素,你需要為每個元素對應的塊提供一個唯一的

key

attribute:

<script>
    export default {
        data() {
            return {
                userList: [
                    { name: "張三", age: 19, address: "北京" },
                    { name: "李四", age: 29, address: "上海" },
                    { name: "王五", age: 39, address: "廣州" }
                ]
            }
        },
        methods: {
            addUser() {
                this.userList.unshift({ name: "小白", age: "8", address: "成都" })
            }
        }
    }
</script>

<template>
    <!-- :key的使用 -->
    <ul>
        <li v-for="item in userList" :key="item">
            <input type="checkbox">{{ item.name }}
        </li>
    </ul>
    <button @click="addUser">添加user</button>
</template>
           

數組變化偵測

Vue 能夠偵聽響應式數組的變更方法,并在它們被調用時觸發相關的更新。這些變更方法包括:

  • push()

  • pop()

  • shift()

  • unshift()

  • splice()

  • sort()

  • reverse()

計算屬性

計算屬性隻會在依賴值發生變化時才會重新計算。

<script >
export default {
    data() {
        return {
            message: "hello world",
            firstMsg: "abc",
            lastMsg: "efg"
        }
    },
    //方法
    methods: {
        reverseMsg2() {
            console.log("reverseMsg2");
            return this.message.split("").reverse().join("");
        }
    },
    //計算屬性
    computed: {
        reverseMsg() {
            console.log("reverseMsg");
            return this.message.split("").reverse().join("");
        },
        // 可寫計算屬性
        fullName: {
            // getter
            get() {
                return this.firstMsg + "-" + this.lastMsg;
            },
            // setter
            set(newValue) {
                [this.firstMsg, this.lastMsg] = newValue.split(" ");
            }
        }
    }
}
</script>

<template>
    <p>{{ message }}</p>
    <p>{{ reverseMsg2() }}</p>
    <p>{{ reverseMsg2() }}</p>
    <p>{{ reverseMsg }}</p>
    <p>{{ reverseMsg }}</p>
    <button @click="message = '你好'">修改message</button>
    <p>{{ fullName }}</p>
    <p>{{ fullName="ABC EFG" }}</p>
</template>
           

說明:

列印了2次“reverseMsg2”,說明每次調用方法都會執行一次;列印了1次“reverseMsg”,說明計算屬性會緩存。

點選按鈕修改了message屬性,會重複上面操作,說明計算屬性隻有依賴值發生變化時才會重新計算。

偵聽器

監聽狀态變化。

<script >
export default {
    data() {
        return {
            message: "hello world",
            isHidden: true,
            user: {
                name: "小明",
                age: 18,
                sex: true
            }
        }
    },
    // 偵聽器
    watch: {
        // 偵聽器,方式一,message發生變化時調用
        // message(newValue, oldValue) {
        //     console.log("新值:" + newValue, "舊值:" + oldValue);
        //     if (newValue.length < 5 || newValue.length > 10) {
        //         this.isHidden = false;
        //     } else {
        //         this.isHidden = true;
        //     }
        // }

        // 偵聽器,方式二,初始化時觸發
        message: {
            immediate: true, // 是否初始化時調用
            handler(newValue, oldValue) {
                if (newValue.length < 5 || newValue.length > 10) {
                    this.isHidden = false;
                } else {
                    this.isHidden = true;
                }
            }
        },
        // 深度監聽,方式一,監聽對象的每個屬性
        // user: {
        //     handler(newValue) {
        //         console.log(newValue);
        //         console.log(newValue.name);
        //     },
        //     deep: true // 是否深度監聽,給對象的每個屬性都加上偵聽器
        // },
        // 深度監聽,方式二,監聽對象的單個屬性
        "user.name": {
            handler(newValue) {
                console.log(newValue);
            },
            deep: true // 是否深度監聽
        }
    }
}
</script>

<template>
    <p>{{ message }}</p>
    <button @click="message = '你好'">修改message</button><br>
    <input type="text" v-model="message"><br>
    <p :hidden="isHidden">輸入框中的内容不能小于5或大于10</p>
    <button @click="user.name = '小白'">修改user.name</button>
</template>
           

v-bind 屬性綁定

  • v-bind:

    可簡寫為

    :

    ,如

    v-bind:class

    簡寫為

    :class

<script >
export default {
    data() {
        return {
            message: "hello wold",
            //class
            isActive: true,
            isBgColor: true,
            classObj: {
                active: true,
                bgColor: true
            },
            error: null,
            activeClass: "active",
            bgColorClass: "bgColor",
            //style
            activeColor: "red",
            bgColor: "grey",
            fontSize: "30px",
            styleObj: {
                color: "red",
                'background-color': "grey",
                fontSize: "30px"
            }
        }
    },
    // 計算屬性
    computed: {
        classObject() {
            return {
                active: this.isActive && !this.error,
                bgColor: this.isBgColor && !this.error
            }
        }
    }
}
</script>

<template>
    <!-- 使用class -->
    <p class="active">hello world1</p>
    <!-- 綁定對象 -->
    <p :class="{ active: isActive }">hello world2</p>
    <p :class="{ active: isActive, bgColor: isBgColor }">hello world3</p>
    <!-- 綁定對象簡寫 -->
    <p :class="classObj">hello world4</p>
    <!-- 計算屬性 -->
    <p :class="classObject">hello world5</p>
    <!-- 綁定數組 -->
    <p :class="[activeClass, bgColorClass]">hello world6</p>

    <button @click="isActive = !isActive">修改active</button>
    <button @click="isBgColor = !isBgColor">修改bgColor</button>


    <!-- 使用内聯樣式 -->
    <p style="color:red;">hello1</p>
    <!-- 綁定對象 -->
    <p :style="{ color: activeColor, 'background-color': bgColor, fontSize: fontSize }">hello2</p>
    <!-- 綁定對象 -->
    <p :style="styleObj">hello3</p>
    <!-- 綁定數組 -->
    <p :style="[styleObj]">hello4</p>
</template>

<style>
.active {
    color: red;
}

.bgColor {
    background-color: grey;
}
</style>
           

v-on 事件綁定

  • v-on

    可以簡寫為

    @

    ,如

    v-on:click

    簡寫為

    @click

<script >
export default {
    data() {
        return {
            num: 0,
            score: 0
        }
    },
    methods: {
        add(event) {
            this.num++;
        },
        add2(n) {
            this.num += n;
        },
        add3(event, n) {
            this.num += n;
            console.log(event);
        },
        addScore() {
            this.score++;
        },
        fatherClick() {
            console.log("父元素點選");
        },
        childClick() {
            console.log("子元素點選");
        },
        mclick() {
            console.log("送出成功");
        },
        onceClick() {
            console.log("aaa");
        },
        keyupFn(e) {
            console.log("按鍵修飾符:", e.key);
        },
        keyupEnterFn(e) {
            console.log("enter");
        },
        keyupDirectionFn(e) {
            console.log("監聽方向鍵:", e.key);
        },
        rightClickFn() {
            console.log("滑鼠左鍵");
        },
        ctrlFn() {
            console.log("ctrlFn");
        }
    }
}
</script>

<template>
    <!-- 點選事件: -->
    <!-- 綁定事件,直接通過js代碼處理 -->
    <button @click="num++">{{ num }}</button><br>

    <!-- 綁定事件,沒有傳參 -->
    <button @click="add">{{ num }}</button><br>

    <!-- 綁定事件,傳遞參數 -->
    <button @click="add2(5)">{{ num }}</button><br>

    <!-- 綁定事件,擷取傳參和事件對象 -->
    <button @click="add3($event, 5)">{{ num }}</button><br>

    <!-- 綁定多個處理函數 -->
    <button @click="add(), addScore()">{{ num }} --- {{ score }}</button>

    <!-- 事件修飾符: -->
    <!-- 阻止事件冒泡 -->
    <div @click="fatherClick">
        <button @click.stop="childClick">阻止事件冒泡</button>
    </div>
    <!-- 阻止預設送出 -->
    <form action="">
        <input type="submit" value="阻止預設送出" @click.prevent="mclick">
    </form>
    <!-- 隻會觸發一次 -->
    <button @click.once="onceClick">隻觸發一次</button><br>
    <!-- 按鍵修飾符: -->
    <input type="text" placeholder="按鍵修飾符" @keyup="keyupFn"><br>

    <!-- 按鍵别名 -->
    <!-- 監聽按鍵輸入 -->
    <input type="text" placeholder="enter别名" @keyup.enter="keyupEnterFn"><br>
    <!-- 監聽方向鍵 -->
    <input type="text" placeholder="監聽方向鍵" @keyup.left.right.down.up="keyupDirectionFn"><br>
    <!-- 系統按鍵, -->
    <input placeholder="ctrl" @keyup.ctrl="ctrlFn" /><br>

    <!-- 滑鼠按鍵:該按鍵必須在事件發出時處于按下狀态。 -->
    <button @click.right="rightClickFn">滑鼠按鍵</button>
</template>
           

v-model 雙向綁定

v-model

可以在元件上使用以實作雙向綁定。

<script >
export default {
    data() {
        return {
            msg: "hello world",
            checked: true,
            fruits: [],
            sex: "男",
            city: "上海",
            citys: [],
            desc: "abc",
            num: 0,
            inputMsg: ""
        }
    },
    methods: {
        changeMsg(e) {
            this.msg = e.target.value;
        },
        changeInput(e) {
            console.log(this.inputMsg);
        }
    }
}
</script>

<template>
    <!-- v-model雙向綁定 -->
    <input type="text" v-model="msg">
    <h3>{{ msg }}</h3>

    <!-- v-model原理: -->
    <input type="text" :value="msg" @input="changeMsg"><br>

    <!-- 單個多選框 -->
    <input type="checkbox" v-model="checked">
    <p>{{ checked }}</p>

    <!-- 多選框 -->
    <label><input type="checkbox" v-model="fruits" value="蘋果">蘋果</label>
    <label><input type="checkbox" v-model="fruits" value="梨子">梨子</label>
    <label><input type="checkbox" v-model="fruits" value="香蕉">香蕉</label>
    <label><input type="checkbox" v-model="fruits" value="西瓜">西瓜</label>
    <p>你喜歡的水果:{{ fruits }}</p>

    <!-- 單選框 -->
    <input type="radio" v-model="sex" value="男">男
    <input type="radio" v-model="sex" value="女">女
    <p>你的性别:{{ sex }}</p>

    <!-- 單選選項框 -->
    <select v-model="city">
        <option value="北京">北京</option>
        <option value="上海">上海</option>
        <option value="廣州">廣州</option>
    </select>
    <p>你選的城市:{{ city }}</p>

    <!-- 多選框 -->
    <select v-model="citys" multiple>
        <option value="北京">北京</option>
        <option value="上海">上海</option>
        <option value="廣州">廣州</option>
    </select>
    <p>你喜歡城市:{{ citys }}</p>

    <!-- v-model修飾符: -->
    <!-- .lazy 當輸入框失去焦點時執行 -->
    <input type="text" v-model.lazy="desc">
    <p>{{ desc }}</p>
    <!-- .number 将輸入框的内容轉為number類型 -->
    <input type="text" v-model.number="num">
    <p>{{ num }} 類型:{{ typeof num }}</p>
    <!-- .trim 清楚前後空格 -->
    <input type="text" v-model.trim="inputMsg" @input="changeInput">
</template>