Vue2基礎

HuangQiaoqi發表於2024-05-04

【一】初識Vue

【1】什麼是Vue

Vue 是一套用於構建使用者介面的漸(逐漸)進(遞進)式 JavaScript 框架

Vue 可以自底向上逐層應用,由國人尤雨溪開發

採用元件化模式,提高程式碼的複用率、讓程式碼更好維護

宣告式編碼方式,讓編碼人員無需直接操作 DOM,提高開發效率

使用虛擬DOM + 優秀的 Diff 演算法,儘量複用 DOM 節點

Vue.js 的核心是一個允許採用簡潔的模板語法來宣告式地將資料渲染進 DOM 的系統:

【2】引入Vue

本地方式引入

<script src="../js/vue.js"></script>

網路CDN方式引入

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>

【3】Vue基本結構

在初學階段,Vue 的結構由 容器 + 物件 兩大部分構成

<body>
<div id="app">
    {{name}}
    {{age}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app', // 這是Vue物件所繫結的容器物件,一般使用css選擇器繫結
        data: {     // data用於儲存資料
            name: 'green',
            age: 18
        }
    })
</script>

【二】基礎知識

【1】模板語法

插值語法

<body>
<div id="app">
    {{name}}
    <br>
    {{age}}
    <br>
    {{hobby}}|{{hobby[0]}} // 陣列只能用中括號取值
    <br>
    {{obj}}|{{obj.name}}|{{obj["name"]}} // 物件可以用中括號或者點屬性取值
    <br>
    {{link}}
</div>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: 'green',
            age: 18,
            hobby: ['洗衣服', '做飯', '打遊戲'],
            obj: {name: "hqq", age: 22, hobby: ['抽菸', '喝酒', '洗腳']},
            link: '<a href="https://meizi5.com">點選看美女</a>'
        }
    })
</script>
</body>

指令語法

<div id="root">
    <!-- v-bind 可以簡寫為 : -->
    <a v-bind:href="url">點我去百度 - 完整寫法</a>
    <a :href="url">點我去百度 - 簡略寫法</a>
</div>

<script>
    new Vue({
        el: '#root',
        data: {
            url: 'https://www.baidu.com'
        }
    })
</script>

總結

​ 插值語法

​ 功能:用於解析標籤體中的內容

​ 寫法:{{xxxx}},其中 xxxx 是 js 表示式,且可以直接讀取到 data 中的所有屬性

​ 指令語法

​ 功能:用於解析標籤(包括:標籤屬性,標籤體內容,繫結事件)

【2】資料繫結

單向繫結:str變---》input框變,input框變---》str不變

單向繫結:str變---》input框變,input框變---》str也變

<div id="app">
單向繫結 <input type="text" :value="str">
雙向繫結 <input type="text" v-model:value="str">
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            str: '炎帝蕭炎'
        }
    })
</script>
</body>

總結

總結:

單向繫結(v-bind):資料只能由 data 流向頁面

雙向繫結(v-model)

資料既能從 data 流向頁面,也能從頁面流向 data

雙向繫結一般都應用在表單類元素上(input、select...)

v-model:value 可以簡寫為 v-model,因為 v-model 預設繫結的就是 value 屬性

【3】事件指令

es6的物件寫法

// es6 的物件寫法
var hobby=['抽菸','燙頭']
var obj={  
    'name':'hqq',
    age:19,  // 鍵值可以不帶引號 
    hobby, // 可以直接省略鍵名,在有定義的情況下
    showName() {
        console.log(this.name)
      // 函式可以省略:function
    }
}

函式傳引數問題

<body>
<div id="app">
    <button v-on:click="showFunc1">不傳引數,函式有引數(會自動把當前事件傳入)</button>
    <button v-on:click="showFunc2(name)">傳引數,函式有引數(正常輸出)</button>
    <button v-on:click="showFunc3($event)">傳引數,函式有引數,把事件物件傳入(正常輸出)</button>
    <button v-on:click="showFunc4()">傳引數,函式有多個引數,少傳引數(少傳就輸出傳入的,多傳就不關多出來的)</button>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            name: 'green'
        },
        methods: {
            showFunc1(event) {
                console.log(event)
            },
            showFunc2(param) {
                console.log(param)
            },
            showFunc3(event) {
                console.log(event)
            },
            showFunc4(a,b,c) {
                console.log(a,b,c)
            }
        }
    })
</script>

【4】屬性指令

1. 標籤上有屬性 如:
img的src屬性,a標籤的href屬性

2. 屬性指令的作用就是使用變數動態的設定屬性的值

3. 使用方法
	v-bind:屬性名='變數'
    簡寫
    :屬性名='變數'

動態切換美女圖片案例

<body>
<div id="app">
    <button @click="handleClick">點選切換自動切換美女</button>
    <img :src="src" alt="">
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            list: ['/img/1.jpg', '/img/2.jpg', '/img/3.jpg'],
            src: '',
            index: 0,
            flag: false,
            t: null
        },
        methods: {
            handleChange() {
                console.log(this.index)
                this.src = this.list[this.index]
                this.index += 1
                if (this.index === 3) {
                    this.index = 0
                }
            },
            handleClick() {
                if (this.flag === false) {
                    this.t = setInterval(this.handleChange, 1000)
                    this.flag = true
                } else {
                    clearInterval(this.t)
                    this.flag = false
                }

            }
        }
    })
</script>
</body>

補充:js中的計時器

js 定時器有以下兩個方法:

setInterval() :按照指定的週期(以毫秒計)來呼叫函式或計算表示式。方法會不停地呼叫函式,直到 clearInterval() 被呼叫或視窗被關閉。
setTimeout() :在指定的毫秒數後呼叫函式或計算表示式。

語法
setInterval(code,millisec,lang)
code 必需。要呼叫的函式或要執行的程式碼串。
millisec  	必須。週期性執行或呼叫 code 之間的時間間隔,以毫秒計。
lang	可選。 JScript | VBScript | JavaScript

【5】style和class

# 1 class 可以繫結 字串,陣列,物件
	字串: 'div1 div2'---》字串替換控制樣式
    陣列:['div1','div2']--->追加陣列,刪除陣列控制樣式
    物件:{div1: true, div2: true, div3: true, div4: false}--》透過true和false控制樣式
    
# 2 style 可以繫結 字串,陣列,物件
	字串'background-color: green;height: 300px;width: 300px'---》字串替換控制樣式
    陣列:[{'background-color': 'green'}, {height: '300px'}, {width: '300px'}]--->追加陣列,刪除陣列控制樣式
    物件:{backgroundColor: 'green', height: '330px', width: '300px'} --》透過根據key修改value控制樣式

    
    
# 3 坑:以後如果改了物件,或陣列,發現頁面沒有變化,實際上值被真正的改了
	Vue.set(this.style_list,3,{'margin':'auto'})
    

【6】條件渲染

v-if v-else-if v-else

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./vue/vue.js"></script>
    <style>

    </style>
</head>
<body>
<div id="app">
    <h1>條件判斷</h1>
    <h2>分數是:{{score}}</h2>
    <h3 v-if="score>=90&&score<=100">優秀</h3>
    <h3 v-else-if="score>=80&&score<90">良好</h3>
    <h3 v-else-if="score>=60&&score<80">及格</h3>
    <h3 v-else>不及格</h3>


</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            score: 99

        }

    })


</script>
</html>

【7】列表渲染

透過使用v-for迴圈顯示多條資料

購物車案例

<body>
<div class="container text-center" id="app">
    <div class="row">
        <div class="col-6 offset-3">
            <h1 class="text-center">購物車</h1>
            <button class="btn btn-success" @click="showGood">載入購物車</button>
            <div v-if="!good_list">空空如也</div>
            <table class="table table-info">
                <thead>
                <tr>
                    <th scope="col">商品ID</th>
                    <th scope="col">商品名稱</th>
                    <th scope="col">商品數量</th>
                    <th scope="col">商品價格</th>
                    <th scope="col">商品圖片</th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="good in good_list">
                    <th scope="row">{{good.id}}</th>
                    <td>{{good.name}}</td>
                    <td>{{good.number}}</td>
                    <td>{{good.price}}</td>
                    <td><img v-bind:src="good_img" alt="" v-bind:style="style_dic"></td>
                </tr>
                </tbody>
            </table>
        </div>
    </div>
</div>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            good_list: null,
            good_img: null,
            style_dic: {}
        },
        methods: {
            showGood() {
                this.good_list = [
                    {'id': 1, 'name': '短裙', 'number': 20, 'price': 22},
                    {'id': 2, 'name': '黑絲', 'number': 34, 'price': 43},
                    {'id': 3, 'name': '白絲', 'number': 55, 'price': 12},
                    {'id': 4, 'name': '過膝襪', 'number': 19, 'price': 5},
                    {'id': 5, 'name': '馬油襪', 'number': 39, 'price': 3},
                ]
                this.good_img = '/img/1.jpg'
                Vue.set(this.style_dic, 'width', '30px')
                Vue.set(this.style_dic, 'height', '30px')
            }
        }
    })
</script>
</body>

for迴圈不同資料型別

<body>
<div id="app">
    <h1>for迴圈字串</h1>
    <p>預設迴圈字元,還可以加入第二個引數,迴圈索引</p>
    <p v-for="(item,index) in str">字元--->{{item}} 索引--->{{index}}</p>

    <h1>for迴圈數字</h1>
    <p>從1開始迴圈到最後一個數字(包括最後一個數字)也可以迴圈索引</p>
    <p v-for="(item,index) in num">數字--->{{item}} 索引--->{{index}}</p>

    <h1>迴圈陣列</h1>
    <p>預設迴圈元素,還可以加入第二個引數,迴圈索引</p>
    <p v-for="(item,index) in list">元素--->{{item}} 索引--->{{index}}</p>

    <h1>迴圈物件</h1>
    <p>預設迴圈value值,還可以加入第二個引數,迴圈鍵值</p>
    <p v-for="(value,key) in obj">值--->{{value}} 鍵--->{{key}}</p>
</div>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            list: ['張雪峰', '暴叔', '吉田'],
            str: 'hello word',
            obj: {name: 'green', age: 18},
            num: 10
        }
    })
</script>
</body>

標籤內加入key屬性

#1 以後寫v-for,都要在標籤上加  :key="key"  ,key必須唯一

# 2 這樣做可以提高虛擬dom的替換效率

【8】事件處理

# 1 input 標籤的事件處理
    input	當輸入框進行輸入的時候 觸發的事件
    change	當元素的值發生改變時 觸發的事件
    blur	當輸入框失去焦點的時候 觸發的事件
    focus   當獲得焦點的時候 觸發的事件
<body>
<div id="app">
    <input type="text" @input="handleInput($event)" value="當輸入框進行輸入的時候 觸發的事件"><br>
    <input type="text" @change="handleChange" value="當元素的值發生改變時 觸發的事件"><br>
    <input type="text" @blur="handleBlur" :value="inputValue"><br>
    <input type="text" @focus="handleFocus" :value="inputValue"><br>

</div>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            inputValue: ''
        },
        methods: {
            handleInput(event) {
                console.log(event.data)
            },
            handleChange() {
                alert('發生改變了')
            },
            handleBlur() {
                this.inputValue = '失去焦點了'
            },
            handleFocus(){
                this.inputValue = '得到焦點了'
            }
        }
    })
</script>
</body>

過濾小案例

<body>
<div id="app" class="container-fluid">
    <div class="row">
        <div class="col-6 offset-3">
            <h1 class="text-center">過濾小案例</h1>
            <p class="text-center">搜尋框</p>
            <input type="email" class="form-control" v-model:value="kewWord" @input="handleInput">
            <table class="table">
                <tr v-for="item in list">
                    <td class="text-center">{{item}}</td>
                </tr>
            </table>
        </div>
    </div>
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            dataList: ['黑絲', '黑絲襪', '黑絲連體襪', '吊帶', '吊帶蝴蝶結', 'black', 'blac', 'bla'],
            kewWord: 'hahah',
            list: null
        },
        methods: {
            handleInput() {
                let _this = this
                this.list = this.dataList.filter(function (item) {
                    return item.indexOf(_this.kewWord) >= 0
                })
            }
        }

    })
</script>
</body>

# 箭頭函式最佳化程式碼寫法
methods: {
            handleInput() {
                this.list = this.dataList.filter((item)=> item.indexOf(this.kewWord) >= 0
                )
            }
        }

// 流程
核心是 要透過輸入框的內容過濾資料列表
輸入框的內容可以透過雙向繫結得到

透過filter函式過濾,它可以將陣列裡的一個個元素分別進行校驗,如果不透過返回flase,透過返回true

透過 indexOf 方法校驗當前輸入框的內容和資料陣列裡的元素是否匹配 如果匹配返回大於0的數,不匹配返回-1

補充:js中的filter函式

filter() 方法建立一個新的陣列,新陣列中的元素是透過檢查指定陣列中符合條件的所有元素。

注意: filter() 不會對空陣列進行檢測。

注意: filter() 不會改變原始陣列。

語法
array.filter(function(currentValue,index,arr), thisValue)

currentValue 當前從array取出校驗的元素
index 當前取出的元素的索引
arr 當前元素的來源

補充:es6語法箭頭函式

    <!--  初始匿名函式寫法-->
    let name = 'green'
    let f = function (name){
      return name + 'nb'
    }
    console.log(f(name))

    // 箭頭函式寫法,去掉function,在括號和大括號中間加上=>
    let f = (name) => {
        return name + 'nb'
    }
    console.log(f(name))


    // 當函式只需要傳一個引數時,可以不用 用括號把引數括起來
    let f = name => {
        return name + 'nb'
    }
    console.log(f(name))


    //  當返回值只有一行程式碼時,可以不用寫return 和 大括號
    let f = name => name + 'nb'

    console.log(f(name))

為什麼要寫箭頭函式?

箭頭函式是為了解決function函式的this指向問題,
箭頭函式體內的this物件,就是定義該函式時所在的作用域指向的物件,而不是使用時所在的作用域指向的物件。

【9】事件修飾符

​ 在Vue中,事件修飾符處理了許多DOM事件的細節,讓我們不再需要花大量的時間去處理這些煩惱的事情,而能有更多的精力專注於程式的邏輯處理。

在Vue中事件修飾符主要有:

.stop:等同於JavaScript中的event.stopPropagation(),防止事件冒泡

.prevent:等同於JavaScript中的event.preventDefault(),防止執行預設的行為(如果事件可取消,則取消該事件,而不停止事件的進一步傳播)

.capture:與事件冒泡的方向相反,事件捕獲由外到內

.self:只會觸發自己範圍內的事件,不包含子元素

.once:只會觸發一次

【10】jsfor迴圈的方式

普通的索引迴圈

<script>
    <!--    普通的索引迴圈-->
    let arr = [18, 'green', {name: 'hqq', age: 22}]
    for(let i=0 ;i<arr.length;i++){
        console.log(arr[i])
    }
</script>

基於迭代的off迴圈

<script>
    <!--    迭代off迴圈-->
    let arr = [18, 'green', {name: 'hqq', age: 22}]
    for (let item of arr) { // item就是陣列裡面的一個個元素
        console.log(item)
    }
</script>

基於迭代的in迴圈

<script>
    <!--    迭代in迴圈-->
    let arr = [18, 'green', {name: 'hqq', age: 22}]
    for (let index in arr) { // index是索引
        console.log(arr[index])
    }
</script>

陣列的forEach方法迴圈

<script>
    <!--    陣列的forEach方法迴圈-->
    let arr = [18, 'green', {name: 'hqq', age: 22}]
    arr.forEach((value,index,array)=>{ // 分別是元素,索引,資料來源陣列
        console.log(value,index,array)
    })
</script>

【11】按鍵修飾符

#1 按下某個鍵盤,觸發事件,透過修飾控制只有按下某個鍵,才觸發事件
#2 keyCode對應表--》按鍵修飾符
	https://www.cnblogs.com/841019rossi/p/16808455.html


<body>
<div id="app">
  <button @keyup.enter="handleEnter">按回車有驚喜</button>
</div>

<script>
  let vm = new Vue({
    el: '#app',
    data:{},
    methods:{
      handleEnter(){
        alert('回車被按了')
      }
    }
  })
</script>
</body>

【12】表單控制

# 1 checkbox   v-model 繫結 
	-布林 :選中沒選中
    -陣列:多選
# 2 radio:
	-字串:value的值

購物車小案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-/mhDoLbDldZc3qpsJHpLogda//BVZbgYuw6kof4u2FrCedxOtgRZDTHgHUhOCVim"
            crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app" class="container">
    <div class="row">
        <div class="col-6 offset-3">
            <h1 class="text-center">圖書商城</h1>
            <p class="text-center">
                <button class="btn btn-success" @click.once="handleLoad">載入購物車</button>
            </p>
            <div class="input-group mb-3">
                <input type="text" class="form-control" placeholder="搜尋書名"
                       aria-label="Recipient's username" aria-describedby="button-addon2" v-model="searchText">
                <button class="btn btn-outline-secondary" type="button" id="button-addon2" @click="handleSearch" >搜尋
                </button>
            </div>
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th scope="col">id</th>
                    <th scope="col">書名</th>
                    <th scope="col">作者</th>
                    <th scope="col">價格</th>
                    <th scope="col">數量</th>
                    <th scope="col"><p>全選/全不選 <input type="checkbox" v-model="checkAll" @change="handleChange"></p>
                    </th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(book,index) in showList">
                    <th scope="row">{{index + 1}}</th>
                    <td>{{book.title}}</td>
                    <td>{{book.author}}</td>
                    <td>{{book.Price}}</td>
                    <td>
                        <button class="btn" @click="handleSub(book)">-</button>
                        {{book.num}}
                        <button class="btn" @click="handleAdd(book)">+</button>
                    </td>
                    <td><input type="checkbox" v-model="checkList" @change="handleSum" :value="book"></td>

                </tr>
                </tbody>

            </table>
            <p>總價格</p>
            <input type="text" class="form-control" readonly :value="getSum">
        </div>
    </div>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            bookList: [],
            checkList: [],
            checkAll: null,
            searchText: '',
            showList: []
        },
        methods: {
            handleLoad() {
                axios.get('http://127.0.0.1:8000/api/v1/book/')
                    .then((response) => {
                        for (const responseElement of response.data.results) {
                            responseElement.num = 0
                        }
                        this.bookList = response.data.results
                    })
            },
            handleAdd(book) {
                book.num += 1
                this.handleSum()
            },
            handleSub(book) {
                if (!book.num) {
                    return
                }
                book.num -= 1
                this.handleSum()
            },
            handleSum() {
                this.checkAll = (this.checkList.length === this.bookList.length)
            },
            handleChange() {
                if (this.checkAll) {
                    this.checkList = this.bookList
                } else {
                    this.checkList = []
                }
            },
            handleSearch() {
                this.showList = this.bookList.filter((book) => book.title.indexOf(this.searchText) >= 0)
            }
        },
        computed: {
            getSum() {
                let total = 0
                for (let book of this.checkList) {
                    total += book.num * book.Price
                }
                return total
            }
        }
    })
</script>
</html>

【13】v-model進階

v-model 之 lazy、number、trim
    lazy:等待input框的資料繫結失去焦點之後再變化
    number:數字開頭,只保留數字,後面的字母不保留;字母開頭,都保留
    trim:去除首位的空格

【14】vue與ajax

vue的資料與後端進行互動的ajax方式有:

原生js的ajax(不常用)
jquery封裝的ajax(不常用)
H5自帶的fetch (可能用)
vue的axios(Vue作者推薦用)

原生js的ajax

<!DOCTYPE html>
<html>
<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>Document</title>
</head>
<body>
</body>
<script>
/* ajax */
//post資料傳遞,一般需要介面文件,自己用node寫也是可以的
//建立ajax
var xhr = new XMLHttpRequest;
//請求地址
xhr.open('post', 'url');
//請求頭
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
//因為ajax非同步send還是寫這裡比較好
xhr.send('name=zhangsan&age=18')
xhr.onreadystatechange = function(){
    if (xhr.readyState === 4){
        if (xhr.status>=200 && xhr.status<300){
            var res = xhr.responseText;
            console.log(res);
        }
    }
}
</script>
</html>

jquery封裝的ajax

因為jquery有比較完整的ajax封裝,但它主要是操作DOM和Bom,所以一般也不怎麼用,作為擴充吧

<!DOCTYPE html>
<html>
<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">
    <!-- bootcdn的映象也可以自己下載jquery庫-->
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <title>Document</title>
</head>
<body>
</body>
<script>
/* jquery */
 $.ajax({
     method:'post',
     url:'url',
//     // dataType:"",
     data:{
         name:'zhangsan',
         age:18
    },
     success:res=>{
         console.log(res);
     },
//     // error:err=>{

//     // }
 })
</script>
</html>

H5自帶的fetch

H5自帶的fetch封裝的ajax也是比較好的,現在市面上還有些公司在用

<!DOCTYPE html>
<html>
<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>Document</title>
</head>
<body>
</body>
<script>
/* fetch */
//get,返回值是物件所以需要呼叫then()方法,呼叫出來
 fetch('url?name=zhangsan&age=18').then(res=>res.text()).then(res=>{
      console.log(res);
 })
//post,body裡還是不能用物件
 fetch('url',{
    method:'post',
     body:'name=zhangsan&age=14',
     headers: {
         "content-type": 'application/x-www-form-urlencoded'
     }
     //轉json資料格式
 }).then(res=>res.json()).then(res=>{
      console.log(res);
 })
</script>
</html>

axios庫

主要使用的資料請求方式,因為作者推薦,作者都推薦了嘛,最後還得是看公司,沒要求最好還是axios

使用需要下載axios外掛,使用方法詳見官網:axios官網

<!DOCTYPE html>
<html>
<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>Document</title>
</head>
<body>
</body>
<script src="./node_modules/axios/dist/axios.js"></script>
<script>
/* axios */
//設定全域性令牌,傳送請求就不用特地帶令牌了
axios.defaults.headers['authorization'] = 'token'
//get,可以設定全域性地址提高程式碼複用率,減少自己寫程式碼,就不用每個都寫這麼長的地址,嘿嘿
axios.defaults.baseURL='url'
axios.get('third', {
    params: {
        name: 'lisi',
        age: 20
    }
}).then(res => {
    console.log(res.data);
})
//post
axios.post('/fourth', 'name=a&age=12').then(res => {
    console.log(res);
})
</script>
</html>

【15】計算屬性

# 1  計算屬性是基於它們的依賴進行快取的

# 2 計算屬性只有在它的相關依賴發生改變時才會重新求值

# 3 計算屬性就像Python中的property,可以把方法/函式偽裝成屬性

# 4 寫在computed中,必須返回值--》返回值才是屬性
	-以後把他當屬性用
    -可以被for迴圈

透過計算屬性實現名字首字母大寫

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <input type="text"  v-model="nameText"> ---> {{upperFirst}}
</div>
<script>
    let vm = new Vue({
        el: '#app',
        data:{
            nameText:'',
        },
        methods:{},
        computed:{
            upperFirst(){
                return this.nameText.substring(0, 1).toUpperCase() + this.nameText.substring(1)
            }
        }
    })
</script>
</body>
</html>

【16】監聽屬性

​ 雖然計算屬性在大多數情況下更合適,但有時也需要一個自定義的偵聽器。這就是為什麼 Vue 透過 watch 選項提供了一個更通用的方法,來響應資料的變化。當需要在資料變化時執行非同步或開銷較大的操作時,這個方式是最有用的。

​ 需要監聽哪個屬性,就在watch裡面寫哪個屬性,只要這個屬性傳送改變,就會自動執行這個方法

小案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-/mhDoLbDldZc3qpsJHpLogda//BVZbgYuw6kof4u2FrCedxOtgRZDTHgHUhOCVim"
            crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <button class="btn btn-success" @click="res='python'">python</button>
    <button class="btn btn-info" @click="res='java'">java</button>
    <button class="btn btn-danger" @click="res='go'">go</button>
    result --->{{res}}
</div>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            res: ''
        },
        watch:{ // 想要監聽哪個引數就在watch裡面寫哪個引數,當這個引數發生變化就會自動執行
            // before改變前,back改變後 這兩引數可填可不填
            res(before,back){
                console.log(back,before)
            }
        }
    })
</script>
</body>
</html>

【17】生命週期

​ vue生命週期分別有建立、初始化資料、編譯模板、掛在DOM、渲染-更新-渲染、解除安裝利用鉤子函式完成對應的專案效果

beforeCreate( 建立前 )

在例項化之後,資料的觀測和事件的配置之前的時候呼叫,此時元件的選項物件還未建立,el 和 data 並未初始化,因此無法訪問methods, data, computed等上的方法和資料

created ( 建立後)

在建立之後使用,主要用於資料觀測、屬性和方法的運算,watch/event事件回撥,完成了data 資料的初始化,el沒有。 然而,掛在階段還沒有開始.

beforeMount (掛載前)

用於在掛載之前使用,在這個階段是獲取不到dom操作的,把data裡面的資料和模板生成html,完成了data等初始化,注意此時還沒有掛在html到頁面上

mount (掛載後)

用於掛載之後使用,在這個時候可以獲取到dom操作,比如可以獲取到ref等,操作的dom, 在這個時候只能呼叫一次ajax,在這個時候el和data都可以獲取的到

beforeUpdate (更新前)

在資料更新之前被呼叫,發生在虛擬DOM重新渲染,可以在該鉤子中進一步地更改狀態,不會觸發重複渲染過程

updated (更新後)

在由於資料更改導致地虛擬DOM重新渲染會呼叫,呼叫時,元件DOM已經更新,所以可以執行依賴於DOM的操作,然後在大多是情況下,應該避免在此期間更改狀態,因為這可能會導致更新無限迴圈,但是在伺服器端渲染期間不被呼叫,可以用於監聽某些資料的時候使用鉤子

beforeDestroy(銷燬前)

在這個時候還是可以用this來獲取,可以用於銷燬計時器時候使用,為了防止跳轉到其它頁面該事件還在執行,還可以清除dom事件等

destroy(銷燬後)

在例項銷燬之後呼叫,呼叫後,所以的事件監聽器會被移出,所有的子例項也會被銷燬.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <child v-if="showChild"></child>
    <button @click="showChild=!showChild">點我消失</button>
</div>
</body>
<script>
    Vue.component('Child', {
        template: `
          <div>
          <button @click="handleClick">{{ title }}</button>
          </div>`,
        data() {
            return {
                title: 'hello word'
            }
        },
        methods: {
            handleClick() {
                alert(this.title)
                this.title = '你好世界'
            },
        },
        // 在建立例項之前執行 this.title不會有值 this.$el不會有值
        beforeCreate() {
            console.log('beforeCreate')
            console.log(this.title)
            console.log(this.$el)
        },
        // 建立例項時執行 this.$el不會有值
        created() {
            console.log('Create')
            console.log(this.title)
            console.log(this.$el)
        },
        // 掛載之前執行 this.$el不會有值
        beforeMount() {
            console.log('beforeMount')
            console.log(this.title)
            console.log(this.$el)
        },
        mounted() {
            console.log('mounted')
            console.log(this.title)
            console.log(this.$el)
        },
        // 在沒有更新資料就不會執行, 有更新的話會在更新之前執行
        beforeUpdate() {
            console.log('beforeUpdate')
            console.log(this.title)
            console.log(this.$el)
        },
        //  // 在沒有更新資料就不會執行, 有更新的話會在更新之後執行
        updated() {
            console.log('Updated')
            console.log(this.title)
            console.log(this.$el)
        },
        // 在沒有執行刪除就不會執行, 有刪除操作的話會在刪除之前執行
        beforeDestroy() {
            console.log('beforeDestroy')
            console.log(this.title)
            console.log(this.$el)
        },
        // 在沒有執行刪除就不會執行, 有刪除操作的話會在刪除之後執行
        destroyed() {
            console.log('destroyed')
            console.log(this.title)
            console.log(this.$el)
        }
    })
    let vm = new Vue({
        el: '#app',
        data: {
            showChild: true
        },
        methods: {}
    })
</script>
</html>

【18】元件的使用

​ 元件分為區域性元件和全域性元件,全域性元件可以在根元件的任意位置使用,區域性元件只能使用在父元件裡面

​ 元件中的資料,事件都是獨立的

全域性元件的書寫

<body>
<div id="app">
    <Child></Child>
</div>
</body>


<script>
    // 全域性元件的書寫
    Vue.component('Child', {
        // 需要透過template掛載
        template: `
          <div><h1>我是全域性元件</h1>
          <p>{{ message }}</p>
          <button @click="handleClick">點我顯示名字</button>
          </div>`,
        // data需要寫成一個函式 然後把值寫在函式的返回值裡
        data() {
            return {
                message: '需要寫在根元件裡'
            }
        },
        // 方法的寫法和根元件的寫法一致
        methods: {
            handleClick() {
                this.message = 'green'
            }
        }
    })

    let vm = new Vue({
        el: '#app',

    })
</script>

區域性元件的書寫

<body>
<div id="app">
    <p>{{message}}</p>
    <button @click="handleClick">點選顯示根元件名字</button>
    <Child></Child>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            message: '我是根元件'
        },
        methods: {
            handleClick() {
                this.message = 'green'
            }
        },
        // 在根元件中定義區域性元件,這裡以根元件為例子,定義在哪裡的區域性元件,就只能在哪裡使用
        components:{
            Child:{
                template:`<div><h1>我是區域性元件,根元件的子元件</h1><button @click="handleClick">點我彈窗</button></div>`,
                data(){
                    return{
                        message:'我是子元件Child'
                    }
                },
                methods: {
                    handleClick(){
                        alert(this.message)
                    }
                }
            }
        }
    })
</script>

【19】元件中通訊

​ 各個元件的資料都是獨立的,要想實現各個元件的資料互通,需要用到一些特定的方法

父傳子

<body>
<div id="app">
    <button @click="handleClick">點選給在子元件發訊息</button>
    <!--    1.在子元件標籤中繫結資料屬性-->
    <Child :message="message"></Child>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            message: ''
        },
        methods: {
            handleClick() {
                this.message = '我是來自父元件的訊息--->你好'
            }
        },
        // 定義子元件
        components: {
            Child: {
                template: `
                  <div><h1>我是子元件Child</h1>
                  <p>來自父元件的訊息---->{{ message }}</p></div>`,
                // 2.在子元件中定義props,將子元件標籤中定義的資料屬性鍵值填入props的陣列
                props: ['message']
            }
        }
    })
</script>

子傳父

<body>
<div id="app">
    <h1>我是父元件</h1>
    <img :src="src" width="250px" height="300px" alt="" v-if="src">
    <!--    子元件給父元件傳引數,需要給子元件標籤繫結一個自定義事件-->
    <Child @event="handleEvent"></Child>
</div>
</body>
<script>
    let em = new Vue({
        el: '#app',
        data: {
            src: ''
        },
        methods: {
            handleEvent(src) {
                this.src = src
            }
        },
        components: {
            Child: {
                template: `
                  <div><h1>我是子元件</h1><img :src="src" alt="" width="250px" height="300px" v-if="src">
                  <button @click="handleClick">點選把圖片傳到父元件</button>
                  </div>`,
                data() {
                    return {
                        src: './img/1.jpg'
                    }
                },
                methods: {
                    handleClick() {
                        // 透過this.$emit('event', this.src),第一個引數就是自定義事件的名稱,第二個引數就是傳遞的引數
                        this.$emit('event', this.src)
                        this.src = ''
                    }
                }
            }
        }
    })
</script>

【20】ref屬性

​ ref是Vue2中一個重要的屬性,用於在元件中對DOM元素或者子元件的引用。透過ref,可以在某個元件的內部直接訪問DOM元素或者它的子元件。

​ 在Vue2中可以將ref新增到元素,元件或者子元件的標籤上,然後可以透過元件例項的$refs物件來訪問這些引用

<body>
<div id="app">
    <h1>我是父元件</h1>
    <button @click="handleClick" ref="button">點我看控制檯</button>
    <Child ref="child"></Child>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handleClick() {
                // this是當前Vue的例項
                // this.$refs是一個物件,裡面包含了所有的有ref屬性的標籤的dom物件或者元件物件
                // 1.拿到子元件的屬性
                console.log(this.$refs.child.message)
                // 2.修改子元件的屬性
                this.$refs.child.message = '我是修改後的訊息'
                // 3.呼叫子元件的函式
                this.$refs.child.handleClick('我是來自父元件的引數')
                // 4.給子元件的函式傳引數
            }
        },
        components: {
            Child: {
                template: `
                  <div ><h1>我是子元件</h1> <button @click="handleClick">點我看看</button><p>{{message}}</p></div>`,
                data() {
                    return {
                        message: '我是來自子元件的訊息'
                    }
                },
                methods: {
                    handleClick(name){
                        console.log('我被父元件的事件呼叫了')
                        console.log(name)
                    }
                }
            }
        }

    })
</script>

【21】動態元件

動態元件,就是實現動態切換的元件

記住以下三點,就能掌握動態元件

① 利用 <component/> 元素的 is 屬性

is 屬性應該用 v-bind 修飾(可以簡寫為 :

is屬性應該傳入註冊的元件名

<body>
<div id="app">
    <button @click="name='Girl1'">美女1</button>
    <button @click="name='Girl2'">美女2</button>
    <button @click="name='Girl3'">美女3</button>
<!--   component是一個萬能元件,他的is屬性就決定了它是哪一個元件 -->
    <component :is="name"></component>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            name:''
        }
    })
    Vue.component('Girl1', {
        template: `<div><h1>美女1</h1><img src="./img/1.jpg" alt=""></div>`
    })
    Vue.component('Girl2', {
        template: `<div><h1>美女2</h1><img src="./img/2.jpg" alt=""></div>`
    })
    Vue.component('Girl3', {
        template: `<div><h1>美女3</h1><img src="./img/3.jpg" alt=""></div>`
    })
</script>

【22】keep-alive

​ 在平常開發中,有部分元件沒有必要多次初始化,這時,我們需要將元件進行持久化,使元件的狀態維持不變,在下一次展示時,也不會進行重新初始化元件。

​ 也就是說,keepaliveVue 內建的一個元件,可以使被包含的元件保留狀態,或避免重新渲染 。也就是所謂的元件快取

<keep-alive>是Vue的內建元件,能在元件切換過程中將狀態保留在記憶體中,防止重複渲染DOM。

<!--被keepalive包含的元件會被快取-->
<keep-alive>
    <component><component />
</keep-alive>

【23】插槽

​ 正常情況下,如果已經寫好了一個元件,並且想要往元件裡面新增別的東西,就只能修改元件內容,擴充性很差

​ 所以就出現了插槽的概念,只需要在模板中可能需要更改的地方加上<slot></slot>,後續想要更新內容的時候直接在html裡面加就行

相關文章