【Vue】計算屬性 監聽屬性 元件通訊 動態元件 插槽 vue-cli腳手架

2023-02-17 18:00:59

昨日回顧

# 1 checkbox    v-model  只針對於input,做雙向資料繫結
	-單選  :選中或不選中  選中就是true,不選中就是false
    -多選  :陣列,選了多個,把選中的value值放到陣列中

# 2 購物車案例
	-checkbox  多選
    -插值 可以放   函數()  把函數返回結果放在插值中
    -插值中的東西,只要變數發生變化,就會重新重新整理  
    	getprice 使用了 checkbox的陣列----》只要陣列發生變化,getprice就會重新運算,重新整理頁面
        
# 2.1 全選全不選
	-全選的checkbox----》checkbox單選---》布林型別----》每次變化都會觸發handleCheckAll的執行
    	-只要是true,就把 this.checkGroup = this.goodList,
        -只要是false,把this.checkGroup = []
        
    -下面的每個checkbox----》checkbox多選---》陣列型別----》每次變化觸發handelCheckOne
    	-每次都要判斷this.checkGroup長度和this.goodList長度是否一樣,如果一樣說明全選了,全選了就把checkAll 設定為true
        -否則,就是false
            
# 2.2 購物車帶加減
	-加----》繫結點選事件,自增1 
    -減-----》函數判斷,不能小於1 ,如果小於1 ,不讓減了,做提示   
        
# 3 v-model進階   修飾v-model
		-lazy
    	-number
        -trim 

# 4 vue的宣告週期
	-8個生命週期勾點函數
    -created:ajax請求放在這裡
    -destory:銷燬,定時任務,清理掉
    -延遲任務,定時任務
    	-實時跟後端互動
        -秒殺場景
        -實時監控你伺服器cpu的佔用率
        	-折線圖:psutil:cpu核心數,佔用率,記憶體使用率,某個碟符使用率 /user
            -echarts
            
# 5 與後端互動
	-js原生傳送ajax請求
	-jq的ajax
    -fetch方案
    -axios 封裝了原生的ajax
    -跨域問題:瀏覽器的安全策略,不允許向不同域傳送請求,獲取資料
    
    -axios.get('地址').then(res=>{
        res 物件,  res.data  響應體的資料
        
    })
    
# 6 如何實現伺服器端主動推播訊息效果[線上聊天室]
	-http  輪詢  長輪詢  websocket-不是所有瀏覽器都相容
    
# 7 元件   元件化開發
	-全域性元件
    	Vue.component('名字',{template,data(){return {}},methods,生命週期})
        
    -區域性元件(只能用在當前元件中)   以後咱們用區域性元件用的多
    	components: {
            foo:{}
        }

1 計算屬性

# 插值語法寫函數 --> {{ 函數() }}
如果 {{函數()}} ,每次頁面重新整理,函數都會重新執行
函數---》當屬性來使用,快取

# 計算屬性
計算屬性只有使用的變數發生變化時,才重新運算
計算屬性就像Python中的property,可以把方法/函數偽裝成屬性

插值語法+函數

需求:寫一個輸入框,輸入框右側即時顯示使用者輸入的內容,如果使用者輸入的是英文字母(假設使用者只輸入英文),將輸入的第一個英文字母大寫。

插值語法放入一個函數時{{函數()}},每次頁面重新整理,函數都會重新執行。
可能出現一種情況,比如只是重新整理了頁面的某一個部分,此時不想讓函數重新計算。由於函數這種自動更新不是我們想要的,所以需要使用:計算屬性。也就是把函數當作屬性來使用,並且視情況來決定是否需要更新。

擷取到字串0到1位置的字元:slice(0,1),並且將其轉大寫:toUpperCase()

範例:

我們再寫一個輸入框:

問題在於,我們在這第二個輸入框進行操作時,函數handleUpper()會一直執行,這是很消耗資源的(每次輸入函數都會執行):

也就是隻要頁面重新整理,無論跟它有沒有關係,都會執行。

使用計算屬性

在設定項computed裡面寫函數,這些函數會當屬性使用。注意這些函數都需要有return值。

使用計算屬性的時候無需加括號:

只有計算屬性使用的變數發生變化時,計算屬性才會發生變化。並且將計算屬性當作屬性用即可。可以使用for迴圈。

程式碼:

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

    <!--    <h1>input輸入單詞,首字母轉成大寫展示</h1>-->
    <!--    <input type="text" v-model="mytext">&#45;&#45;&ndash;&gt;{{mytext.slice(0, 1).toUpperCase() + mytext.slice(1)}}-->


    <h1>input輸入單詞,首字母轉成大寫展示---函數方式---》只要頁面重新整理,無論跟它有沒有關,都會重新運算</h1>
    <!--    <input type="text" v-model="mytext">&#45;&#45;&ndash;&gt;{{getUpper()}}-->
    <input type="text" v-model="mytext">---->{{newText}}

    <br>
    <input type="text" v-model="age">--->{{age}}

</div>

</body>
<script>

    var vm = new Vue({
        el: '.app',
        data: {
            mytext: '',
            age: 10
        },
        methods: {
            getUpper() {
                console.log('函數---我執行了')
                return this.mytext.slice(0, 1).toUpperCase() + this.mytext.slice(1)
            }
        },
        // 計算屬性---->computed 裡面寫方法,以後,方法當屬性用 ,一定要有return值
        computed: {
            newText() {
                console.log('計算屬性---我執行了')
                return this.mytext.slice(0, 1).toUpperCase() + this.mytext.slice(1)
            }
        }


    })
</script>
</html>

計算屬性重寫過濾案例

範例;

範例:

計算屬性中使用了mytext,因為mytext變化了,所以計算屬性會重新整理。並且因為是計算屬性,所以可以使用v-for迴圈。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div>
    <div class="app">
        <h1>過濾案例</h1>
        <p>請輸入要搜尋的內容:<input type="text" v-model="myText"></p>
        <ul>
            <li v-for="item in newDateList">{{item}}</li>
        </ul>

    </div>

</div>
</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            myText: '',
            dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],
        },
        computed: {
            newDateList() {
                return this.dataList.filter(
                    item => item.indexOf(this.myText) >= 0
                )
            }
        }

    })


</script>
</html>

2 監聽屬性

# 在 data 中定義了一些變數,只要變數發生變化,我們就執行一個函數

watch:{
    屬性名(){
        
    }
}

監聽屬性的用途:

點選按鈕對商品排序。
有個屬性叫sorting,如果點選按鈕這個屬性就會變化:

這個屬性變化,就向後端傳送ajax請求獲取資料。

範例:

監聽course_type,重新顯示頁面。

傳送請求:

設定監聽屬性:

不用傳入course_type,因為全域性的course_type已經被修改了。
監聽屬性不用return值。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div>
    <div class="app">
        <!--        <span @click="handleClick(1)">Python</span>|    <span @click="handleClick(2)">Linux</span>-->
        <span @click="course_type=1">Python</span>| <span @click="course_type=2">Linux</span>
        <div>
            假設有很多課程,點選上面的標籤可以完成過濾
        </div>

    </div>

</div>
</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            course_type: '0'
        },
        created() {
            this.getData()
        },
        methods: {
            getData() {
                // 傳送ajax ,獲取所有課程,通過course過濾
                // http://127.0.0.1:8080/api/v1/courses?course_type=0
            },
            // handleClick(type){
            //     this.course_type=type
            //     this.getData()
            // }
        },
        watch: {
            course_type() {
                console.log('我變化了')
                this.getData()
            }
        }

    })


</script>
</html>

3 元件介紹和定義

# 擴充套件 HTML 元素,封裝可重用的程式碼,目的是複用
	-例如:有一個輪播,可以在很多頁面中使用,一個輪播有js,css,html
	-元件把js,css,html放到一起,有邏輯,有樣式,有html
    
    
# 定義元件 ()
	-全域性元件:全域性可以使用,可以用在任意其它元件中
    -區域性元件:區域性元件只能在定義的位置(元件中)使用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>

</head>
<body>
<div id="app">
    <h1>全域性元件</h1>
    <child></child>
    <hr>
    區域性元件
    <lqz></lqz>
    <hr>

</div>
</body>
<script>
    // 1 定義全域性元件 (必須在一個標籤),元件有自己的資料,方法,生週期.....
    var obj = {
        template: `
          <div>
          <button>後退</button>
          {{ title }}
          <button @click="handleClick">前進</button>
          </div>`,
        data() {
            return {
                title: '標題'
            }
        },
        methods: {
            handleClick() {
                alert('前進')
            }
        },
    }
    Vue.component('child', obj)


    //2 區域性元件


    var lqz = {
        template: `
          <div>
          <h1>我是lqz元件</h1>
          {{ name }}
          <child3></child3>
          <child></child>
          </div>`,
        data() {
            return {
                name: 'lqz'
            }
        },
        components: {
            'child3': {
                template: `
            <div>
              <h2>我是lqz元件內的元件</h2>
              </div>`,
            }
        }
    }
    var vm = new Vue({
        el: '#app',
        data: {},
        components: {
            lqz
        }


    })


</script>
</html>

元件之間資料隔離

# 根元件 和 元件 注意事項
	-new Vew()---->管理div----》根元件
    -自己再定義的全域性元件,區域性元件都是不同元件,不是根組價
   	-元件有自己的html,css,js ---》資料,事件,。。。。。
    -在元件中,this代指當前元件
    -父子元件的data是無法共用的
    -data是1個函數,需要有返回值(return)

元件之中父子之間的data是無法共用的:

這個name是子元件的資料。故此資料無法通過插值語法顯示。

區域性元件的情況:

區域性元件有name這個屬性,但是根元件無法之間使用。

總結:

  • 父子元件的data相互隔離的。
  • 就算父子的data中資料相同,擁有相同的方法,也是互不影響的.

4 元件通訊

父子通訊之父傳子

# 元件間資料不共用 ----> 需要進行資料傳遞

# 父傳子:使用自定義屬性方式

父傳子:使用自定義屬性的方式傳遞資料

child標籤內,寫一個自定義屬性myage。(注意上圖不能屬性使用駝峰體,否則會報錯)

子元件怎麼接受父元件的資料?
使用props設定項。

在子元件的設定項props寫一個列表,列表裡面放著自定義屬性的名字myage。這樣在子元件的template就可以通過插值語法來獲取myage裡攜帶的資料。

自定義屬性不能使用駝峰體:

自定義屬性的區別:

範例:

  • :age="19"給子元件傳遞了一個數位19
  • age="19"給子元件傳遞了一個字串19

屬性驗證:

子元件使用props接受的時候可以進行屬性驗證:

如果傳入的資料型別不是我們指定的資料型別,前端頁面還是會將其渲染,但是控制檯會報錯:

遇到變數名相同的情況,子元件優先用哪個資料?

會使用父元件傳來的資料,但是控制檯會報錯。所以傳自定義屬性的時候,不要跟子元件中變數衝突。

程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>父子通訊之父傳子,通過自定義屬性--->不能用駝峰,不要跟子元件中變數衝突</h1>
    <!--    <h2>字串的age&ndash;&gt;age="age"</h2>-->
    <!--    <child age="age"></child>-->
    <!--    <h2>:age="19"</h2>-->
    <!--    <child :age="19"></child>-->
    <!--    <h2>age="19"</h2>-->
    <!--    <child age="19"></child>-->
    <!--    <h2>:age="age"</h2>-->
    <child :age="age" myname="彭于晏"></child>

    <h1>屬性驗證---》傳入的必須是xx型別</h1>
    <!--    <h2>字串的age&ndash;&gt;age="age"</h2>-->
    <!--    <child age="age"></child>-->
    <!--    <h2>:age="19"</h2>-->
    <!--    <child :age="19"></child>-->
    <!--    <h2>age="19"</h2>-->
    <!--    <child age="19"></child>-->
    <!--    <h2>:age="age"</h2>-->
    <!--    <child :age="age"></child>-->


</div>

</body>
<script>
    // 父中有age,子child 只有name,沒有age,現在把父中的age傳到child中,顯示
    var child = {
        template: `
          <div>
          <button>後退</button>
          首頁--->名字:{{ myname }}--->年齡:{{ age }}
          <button>前進</button>
          </div>`,
        data() {
            return {
                myname: 'lqz'
            }
        },
        // props: ['age'],
        props: {age: Number, myname: String},
    }
    var vm = new Vue({
        el: '.app',
        data: {
            age: 19
        },
        components: {
            child
        }

    })
</script>
</html>

父子通訊之子傳父

# 通過自定義事件

需求:

點選子元件按鈕,將子元件輸入框資料傳遞給父元件顯示。

定義子元件:

在父元件使用子元件傳遞的資料:

通過自定義事件實現子傳父,父元件裡寫函數handleEvent函數,child標籤裡寫自定義事件@myevent

通過傳參的方式傳遞給父元件。

子元件使用this.$emit('事件名',傳遞的資料物件)觸發,child中事件@myevent

事件被觸發,父元件函數handleEvent執行,此時函數的形參mytext可以獲取到子元件傳來的資料,通過資料修改父元件的屬性:

程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <p>子元件傳遞過來的資料: {{mytext}}</p>
    <hr>
    <child @myevent="handleEvent"></child>
    <hr>


</div>

</body>
<script>
    var child = {
        template: `
          <div>
          <input type="text" v-model="mytext">
          <button @click="handleSend">點我傳遞</button>
          </div>`,
        data() {
            return {
                mytext: ''
            }
        },
        methods: {
            handleSend() {
                // alert(this.mytext)
                // 子元件中,觸發自定義事件的執行,會執行父元件自定義事件繫結的函數,有幾個引數,就傳幾個引數
                this.$emit('myevent', this.mytext)
            }
        }

    }


    var vm = new Vue({
        el: '.app',
        data: {
            mytext: ''
        },
        methods: {
            handleEvent(mytext) {
                this.mytext = mytext

            }
        },
        components: {
            child
        }

    })
</script>
</html>

ref屬性

# 自定義屬性和自定義事件  可以實現父子傳值

# ref屬性  可以更方便的實現父子通訊

# ref屬性放在普通標籤上  <input type="text" ref="myinput">
	-可以放在普通標籤上,通過this.$refs.自定義的名字取到的是 原生的dom物件 ---> 可以進行原生dom操作了(不推薦)
    
# ref屬性放在元件上  <child ref="mychild"></child>
    -可以放在元件上:通過this.$refs.自定義的名字取到的是 vc物件(元件物件),既然拿到了元件物件,元件物件中的 變數,方法,都能直接通過 . 的方式呼叫
        -可以之間使用元件物件上的方法和屬性 ---> 子的資料給了父親
        -父元件有個方法執行,需要傳引數,傳入子元件的資料 ---> 子的資料給了父親
        -拿到子物件之間使用父中的資料修改 ---> 父傳子
        -因此不需要關注是子傳父,還是父傳子,直接通過元件物件,使用即可
        

準備:

$字首防止資料汙染:資料被覆蓋。

獲取到的是:

可以獲取到原生的html.

可以放在普通標籤上,通過this.$refs.自定義的名字取到的是 原生的dom物件

檢視Vue物件:

如果不定義ref屬性:

可以進行dom操作:

使用原生dom操作了(不推薦)

ref屬性可以放在元件上:
通過this.$refs.自定義的名字取到的是 vc物件(元件物件)

範例:

父元件註冊:

父元件新增ref屬性:

檢視函數:

前端:

實現子傳父:

以後不需要關注是子傳父還是父傳子。直接通過物件取值賦值即可。

並且可以父元件主動使用子元件的函數:

擴充套件

通常元件之間通訊只能通過一層一層的傳到父元件,再由父元件一層層傳遞資料給子元件,來實現跨元件傳遞。
這樣十分麻煩。
所以可以使用Vuex狀態管理器、cookies,這兩種方式都相當於將資料儲存在一個指定的位置,元件都可以去這個地方獲取資料。

程式碼:

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

    <button @click="handleClick">點我</button>
    ----》{{age}}
    <br>
    <input type="text" ref="myinput">
    <div ref="mydiv">我是div</div>
    <hr>
    <child ref="mychild"></child>
    <hr>


</div>

</body>
<script>
    // 父中有age,子child 只有name,沒有age,現在把父中的age傳到child中,顯示
    var child = {
        template: `
          <div>

          <h1>名字:{{ name }}--->年齡:{{ age }}</h1>
          <button @click="handleClick">點我彈出名字</button>

          </div>`,
        data() {
            return {
                name: 'lqz',
                age: 19
            }
        },
        methods: {
            handleClick() {
                alert(this.name)
            }
        }

    }


    var vm = new Vue({
        el: '.app',
        data: {
            age: 999,

        },
        methods: {
            handleClick() {
                // 1 ref 屬性放在普通標籤上,拿到標籤的dom物件
                // 通過this.$refs可以拿到所有標籤上寫了ref屬性的 標籤 ,物件型別 key值是ref對應的value值, value值是原生dom物件
                // console.log(this.$refs)
                // 直接修改原生dom物件的value屬性,input就能看到有值了
                // this.$refs.myinput.value = 'lqz is handsome'

                //2 ref  屬性放在 元件上,拿到的是 元件物件 ,就可以使用元件物件的屬性和方法
                // console.log(this.$refs)  // 物件中有3個值,兩個普通標籤,一個元件
                // this.$refs.mychild   就是元件物件,可以 .屬性,  .方法
                // this.age = this.$refs.mychild.age
                // 重點:以後就不需要關注是子傳父還是父傳子了,直接通過物件取值賦值即可,而且可以主動呼叫子元件中的函數
                this.$refs.mychild.handleClick()

            }
        },
        components: {
            child
        }


    })
</script>
</html>

5 動態元件

# 動態元件
	
# 小案例:點選不同標籤,顯示不同元件

元件切換:

通過v-if顯示元件切換

定義元件:

使用元件:

新增click事件:

設定預設頁面:

使用點選函數、data屬性控制顯示哪個元件:

使用elementui:

程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <span @click="handleClick('home')">首頁</span>| <span @click="handleClick('order')">訂單</span> | <span
        @click="handleClick('goods')">商品</span>
    <home v-if="chooseType=='home'"></home>
    <order v-else-if="chooseType=='order'"></order>
    <goods v-else></goods>

</div>

</body>
<script>

    var home = {
        template: `
          <div>
          <h1>home頁面</h1>
          </div>`,

    }
    var order = {
        template: `
          <div>
          <h1>order頁面</h1>
          </div>`,

    }
    var goods = {
        template: `
          <div>
          <h1>商品頁面</h1>
          </div>`,

    }


    var vm = new Vue({
        el: '.app',
        data: {
            chooseType: 'home'
        },
        methods: {
            handleClick(type) {
                this.chooseType = type
            }
        },
        components: {
            home,
            order, goods
        }


    })
</script>
</html>

動態元件component標籤

必須使用Vue提供的componment標籤,這個標籤有個is屬性。
is屬性寫哪個自定義元件的名字這個componment標籤就顯示哪個元件。

注意:
這個元件必須要在父元件的componments屬性中註冊,寫這個元件的名字才會顯示。

也就是is對應哪個字串,就顯示哪個元件。

程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <span @click="handleClick('home')">首頁</span>| <span @click="handleClick('order')">訂單</span> | <span
        @click="handleClick('goods')">商品</span>

    <component :is="who"></component>

</div>

</body>
<script>

    var home = {
        template: `
          <div>
          <h1>home頁面</h1>
          </div>`,

    }
    var order = {
        template: `
          <div>
          <h1>order頁面</h1>
          </div>`,

    }
    var goods = {
        template: `
          <div>
          <h1>商品頁面</h1>
          </div>`,

    }


    var vm = new Vue({
        el: '.app',
        data: {
            who: 'home'
        },
        methods: {
            handleClick(type) {
                this.who = type
            }
        },
        components: {
            home,
            order, goods
        }


    })
</script>
</html>

keep-alive保持元件不銷燬

使用動態元件,當切換元件的時候,再切換回來的時候,前一個元件輸入的資訊會被消毀。所以需要使用keep-alive標籤包一下:

相當於做了一層快取。保持元件不被銷燬。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <span @click="handleClick('home')">首頁</span>| <span @click="handleClick('order')">訂單</span> | <span
        @click="handleClick('goods')">商品</span>
    <keep-alive>
        <component :is="who"></component>
    </keep-alive>

</div>

</body>
<script>

    var home = {
        template: `
          <div>
          <h1>home頁面</h1>
          </div>`,

    }
    var order = {
        template: `
          <div>
          <h1>order頁面</h1>
          </div>`,

    }
    var goods = {
        template: `
          <div>
          <h1>商品頁面</h1>
          <input type="text" > <buttont>搜尋</buttont>
          </div>`,

    }


    var vm = new Vue({
        el: '.app',
        data: {
            who: 'home'
        },
        methods: {
            handleClick(type) {
                this.who = type
            }
        },
        components: {
            home,
            order, goods
        }


    })
</script>
</html>

6 插槽

# 插槽出現的原因
一般情況下,編寫完1個元件之後,元件的內容都是寫死的,需要加資料 只能去元件中修改,擴充套件性很差,然後就出現了插槽這個概念。

# 插槽的使用
只需在元件中新增<slot></slot>,就可以在body的元件標籤中新增內容

匿名插槽

範例:

填充插槽:

在父元件監控程式碼內的子元件標籤之間寫的內容,會原封不動的替換到子元件的slot標籤中。

比如子元件的標籤是<home><home>標籤內的所有內容會替換到子元件的shot標籤。

如果有多個插槽,所有插槽都會被替換:

程式碼:

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

    <hr>
    <home>

        <div>
            <img src="./img.png">

在父元件指定替換哪個插槽,使用slot屬性:

使用slot屬性,將這個div替換到子元件name="a"的插槽上。

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

    <hr>
    <home>

        <div slot="a">
            <img src="./img.png">

瀏覽器具備javascript環境:

node.js 基於瀏覽器(有擴充套件)的js直譯器 使得js程式碼能執行在作業系統上。

使得js就可以寫後端。

安裝node.js:

下載16版本:

範例:

npm:

擴充套件

事件匯流排 用的少
自定義指令 太專業
過濾器 用的少

作業

# 獲取所有圖書介面drf寫,處理跨域(響應頭)
# 前端vue專案首頁,只要載入好就獲取所有圖書v-for迴圈顯示在頁面上

----------------------------------------------------------
# 實時監控你機器的cpu使用了,使用折線圖展示