Vue入門到關門之元件

Xiao0101發表於2024-05-02

一、元件

1、什麼是元件

在Vue.js中,元件是構建使用者介面的可重用和獨立的模組。每個Vue元件都封裝了自己的模板、邏輯和樣式,使得程式碼可以更加模組化、可維護性更高。透過元件化,你可以將介面拆分成獨立的、可複用的部分,每個部分都有自己的功能和樣式,這樣可以更容易地管理複雜的介面,並且提高了程式碼的可讀性和可維護性。

通俗來說,元件就是把一個很大的介面拆分為多個小的介面, 每一個小的介面就是一個元件,將大介面拆分成小介面就是元件化。而元件化開發指的就是根據封裝的思想,把頁面上可重用的 UI 結構封裝為元件,從而方便專案的開發和維護。

image

2、元件的分類

  • 按作用範圍分類
    • 全域性元件:專案中所有地方都可以的元件稱為全域性元件
    • 區域性元件(私有元件):僅有該元件才能使用的元件稱為區域性元件
  • 按照用途來分
    • 頁面元件
    • 自定義元件

工程化開發之後:1個元件 就是1個xx.vue在vue 中規定:元件的字尾名是 .vue。之前接觸到的 App.vue 檔案本質上就是一個 vue 的元件。

以CSDN為例,如果使用元件化開發的話:

image

3、元件的內容

在Vue中,一個元件可以包括以下內容:

  1. 模板(Template):定義了元件的結構和佈局,使用HTML和Vue的模板語法來描述介面的外觀。

  2. 指令碼(Script):包含了元件的邏輯,例如資料處理、事件處理、生命週期鉤子等。通常使用JavaScript或TypeScript編寫。

  3. 樣式(Style):定義了元件的樣式,可以使用CSS、Sass、Less等來編寫。

透過元件,你可以將頁面劃分成多個獨立的部分,每個部分都有自己的功能和樣式,並且可以在需要的地方進行重複使用。其中,每個元件中必須包含 template 模板結構,而 script 行為和 style 樣式是可選的組成部分。

(1)template

  • 當前元件的DOM結構,需要定義到template標籤的內部
template:`
  <div>
    <h1>{{ message }}</h1>
    <button @click="changeMessage">Change Message</button>
  </div>
`

注意:

  • template 是 vue 提供的容器標籤,只起到包裹性質的作用,它不會被渲染為真正的 DOM 元素,後面的 v-slot 會使用到這個標籤
  • template 中只能包含唯一的根節點

(2)script

  • 之後與元件相關的data資料、methods方法等,都需要定義到export default所匯出的物件中
data() {
    return {
        message: 'Hello, Vue!'
    };
},
methods: {
    changeMessage() {
        this.message = 'Hello, World!';
    }
}

注意:

.vue 元件中的 data 必須是函式

vue 規定:.vue 元件中的 data 必須是一個函式,不能直接指向一個資料物件。

因此在元件中定義 data 資料節點時,下面的方式是錯誤的,但是在根元件這樣寫是可以的

data:{
    count:0
}

(3)style

  • 還是按照css的語法來寫就好
<style>
h1 {
  color: blue;
}
</style>

總的來說,Vue元件是Vue.js框架中用於構建使用者介面的獨立模組,它們可以被組合和巢狀,從而構建出複雜的介面。

二、元件使用

1、全域性元件

全域性元件是在Vue應用程式中全域性註冊的元件,可以在應用的任何地方使用。一旦註冊為全域性元件,它就可以在整個應用程式中的任何Vue例項的模板中使用。

(1)註冊全域性元件

在Vue中,你可以使用Vue.component方法來註冊全域性元件。例如:

// 全域性註冊一個名為 'my-component' 的元件
Vue.component('my-component', {
  // ... 元件的選項
})

(2)使用全域性元件

一旦註冊為全域性元件,你可以在任何Vue例項的模板中使用它:

<template>
  <div>
    <my-component></my-component>
  </div>
</template>

(3)完整示例

<!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>
    <button @click="handleClick">點我</button>


    <hr>
    <xiao></xiao>
    <hr>
    <h1>我是全域性元件</h1>
    <xiao></xiao>
</div>
</body>
<script>
    // 1、定義全域性元件
    Vue.component('xiao', {
        template: `<div>
            <h1>{{ name }}</h1>
            <button @click="handleClick">點我換名字</button>
          </div>`,
        data() {
            return {
                name: 'xiao'
            }
        },
        methods: {
            handleClick() {
                this.name = '彭于晏'
            }
        }
    })
    
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handleClick() {
                alert('美女吧')
            }
        }
    })
</script>
</html>

2、區域性元件

區域性元件是在Vue例項(或者其他元件)的元件選項中註冊的元件。它只能在註冊它的例項或者元件內部使用。

(1)註冊區域性元件

在Vue例項或者其他元件中,你可以透過components選項來註冊區域性元件。例如:

<template>
  <div>
    <my-local-component></my-local-component>
  </div>
</template>

<script>
// 透過ES6的import將自定義的元件引入進來
import MyLocalComponent from './MyLocalComponent.vue';

export default {
  // 註冊元件
  components: {
    'my-local-component': MyLocalComponent
  }
}
</script>

(2)使用區域性元件

一旦在例項或者元件中註冊了區域性元件,你可以在該例項或者元件的模板中使用它:

<template>
  <div>
    <my-local-component></my-local-component>
  </div>
</template>

(3)完整示例

<!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>
    <button @click="handleClick">點我</button>
    <hr>
    <xiao></xiao>
</div>
</body>
<script>
    var xiao = {
        template: `
          <div>
            <h2>我是區域性元件</h2>
          </div>
        `,
        data() {
            return {}
        },
        methods: {}
    }

    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handleClick() {
                alert('美女吧')
            }
        },
        components: {
            xiao:xiao
        }
    })
</script>
</html>

3、全域性和區域性混合使用

<!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>
    <button @click="handleClick">點我</button>

    <hr>
    <child></child>
</div>
</body>
<script>
    var xiao = {
        template: `
          <div>
            <h2>我是區域性元件</h2>
          </div>
        `,
        data() {
            return {}
        },
        methods: {}
    }

    //  全域性元件
    Vue.component('child', {
        template: `
          <div>
            <h1>我是全域性元件</h1>
            <xiao></xiao>
            <xiao></xiao>
            <xiao></xiao>
          </div>
        `,
        // 區域性元件
        components: {
            // 第一種方法
            // xiao: {
            //     template: `
            //       <div>
            //         <h2>我是區域性元件</h2>
            //       </div>
            //     `,
            //     data() {
            //         return {}
            //     },
            //     methods: {}
            // }

            // 第二種方法
            xiao
        }
    })

    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handleClick() {
                alert('美女吧')
            }
        },
        components: {
            xiao
        }
    })
</script>
</html>

4、總結

  • 全域性元件可以在整個應用程式中的任何地方使用,而區域性元件只能在註冊它的例項或者元件內部使用。
  • 全域性元件適合用於在整個應用中頻繁使用的通用元件,而區域性元件適合用於特定頁面或者元件內部的元件。
  • 全域性元件的註冊是透過Vue.component方法進行,而區域性元件的註冊是透過元件選項中的components屬性進行。
  • 注意:元件中的資料,事件在沒有額外引數的影響下都是獨立的

瞭解elementui:

  • Element UI是一個基於Vue.js的元件庫,提供了豐富的UI元件,如按鈕、表格、彈窗等,可以幫助開發者快速構建美觀、功能完善的前端介面。
  • 使用Element UI不僅可以減少開發工作量,而且它的元件都經過最佳化和測試,在效能和使用者體驗方面表現較好。
  • 透過引入Element UI的全域性元件,開發者可以更加高效地開發出具有一致風格的介面。

三、元件間通訊

image

1、父子通訊之父傳子-自定義屬性

(1)父元件向子元件通訊的步驟

  1. 在父元件中定義變數
data: {
    'url': './img/a.jpg'
}
  1. 把變數傳遞個子元件 ==> 自定義屬性:myurl
<Child1 :myurl="url"></Child1>
  1. 在子元件中,拿到屬性
props:['myurl']
  1. 以後在子元件中使用父元件的屬性
this.myurl

(2)完整示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>
</head>
<body>
<div id="app">
    <h1>元件間通訊之父傳子:自定義屬性</h1>
    <h2>父元件中的名字{{myname}}</h2>
    <div style="background-color: pink">
        <child :name="myname" yy="xx"></child>
    </div>
</div>
</body>
<script>
    // 全域性元件
    Vue.component('child', {
        template: `
          <div>
            <h2>我是child元件</h2>
            <h3>父元件傳遞給子元件的{{ name }}---{{ yy }}</h3>
          </div>`,
        data() {
            return {}
        },
        props: ['name', 'yy']
    })

    var vm = new Vue({
        el: '#app',
        data: {
            myname: '彭于晏'
        },
    })
</script>
</html>

執行結果:

image

2、父子通訊之子傳父---自定義事件

(1)子元件向父元件通訊的步驟

  1. 在父元件中定義變數,用來接收子元件傳入的變數
data: {
    text:''
},
  1. 在父元件使用子元件時候,自定義事件 myevent,名字隨便取
<Child1 @myevent="handleMyEvent"></Child1>
  1. 在父元件中定義函式,跟自定義事件繫結
handleMyEvent(childText){
    this.text=childText
}
  1. 在子元件中 ==> 觸發自定義事件執行
this.$emit('自定義事件名字',this.mytext)

(2)完整示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>
</head>
<body>
<div id="app">
    <h1>元件間通訊之子傳父:自定義事件</h1>
    <h2>我是父元件</h2>
    子元件傳給父元件的值===> {{p_name}}
    <hr>
    <div style="background-color:pink">
        <child @myevent="handleEvent"></child>
    </div>
</div>
</body>
<script>
    // 全域性元件
    Vue.component('child', {
        template: `
          <div>
            <h2>我是child元件</h2>
            <input type="text" v-model="name">--> {{name}}
            <button @click="handleSend">傳給父</button>
          </div>`,
        data() {
            return {
                name:''
            }
        },
        methods:{
            handleSend(){
                this.$emit('myevent',this.name)
            }
        }
    })

    var vm = new Vue({
        el: '#app',
        data: {
p_name:''
        },
        methods: {
            handleEvent(name){
                // name 是子元件中呼叫this.$emit('myevent',this.name)傳過來的
                this.p_name = name
            }
        },
    })
</script>
</html>

執行結果:

image

3、ref屬性(父子通訊)

  • ref 是個屬性, 如果在普通的DOM元素上,引用指向的就是該DOM元素;
  • 如果在子元件上,引用的指向就是子元件例項,然後父元件就可以透過 ref 主動獲取子元件的屬性或者呼叫子元件的方法

(1)放在普通標籤上

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

</head>
<body>
<div id="app">
    <h2>ref屬性放在普通標籤上</h2>
    <input type="text" v-model="name" ref="myinput">
    <img src="./img/2.jpg" alt="" ref="myimg">
    <button @click="handleClick">點我執行程式碼</button>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: ''
        },
        methods: {
            handleClick() {
                console.log(this.$refs)
                // 根據ref指定的名字,取出原生dom物件,然後就可以操作dom物件了
                var i = this.$refs['myinput']
                console.log(i)
                i.value = "你好"
                // 改圖片
                var i = this.$refs['myimg']
                i.src = './img/3.jpg'
            }
        }
    })
</script>
</html>

(2)放在元件上

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>
</head>
<body>
<div id="app">
    <div style="background-color: antiquewhite">
        <h2>ref屬性放在元件上</h2>
        <child ref="mychild"></child>
    </div>
</div>
</body>
<script>
    // 定義全域性元件
    Vue.component('child', {
        template: `
          <div>
            <img :src="url" alt="">
            <button @click="handleClick('子元件傳入的')">點我彈窗</button>
          </div>
        `,
        data() {
            return {
                url: './img/1.jpg'
            }
        },
        methods: {
            handleClick(name) {
                alert(name)
            }
        },
    })

    var vm = new Vue({
        el: '#app',
        data: {
            name: ''
        },
        methods: {
            handleClick() {
                // 操作元件物件
                var i = this.$refs['mychild']
                console.log(i.url)
                // 改圖片
                i.url = './img/4.jpg'
                // 改執行方法
                i.handleClick('xiao')

                // 子傳父
                this.name = i.url
            }
        }
    })
</script>
</html>

四、動態元件

1、概念

動態元件就是允許你根據當前的資料來動態地切換顯示不同的元件。

  • Vue內部提供的元件component元件作用是:實現動態的渲染元件,按需顯示元件。

  • component 標籤是 vue 內建的,作用:元件的佔位符

  • 其中is 屬性的值,表示要渲染的元件的名字

  • is 屬性的值,應該是元件在 components 節點下的註冊名稱

2、完整示例

  • 比如我們這裡有三個元件,需求:在app根元件中點選不同按鈕可以按需顯示元件。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./vue/vue.js"></script>
    <style>
        .item {
            width: 150px;
            height: 50px;
            background-color: pink;
            font-size: 25px;
            margin: 10px;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .top {
            display: flex;
            justify-content: center;
        }
    </style>
</head>
<body>
<div id="app">
    <h1>動態元件</h1>
    <div class="top">
        <div class="item" @click="current='goods'">
            <span>商品</span>
        </div>
        <div class="item" @click="current='order'">
            <span>訂單</span>
        </div>
        <div class="item" @click="current='user'">
            <span>使用者</span>
        </div>
    </div>
    <div>
<!--        不使用動態元件-->
<!--        <goods v-if="current=='goods'"></goods>-->
<!--        <order v-else-if="current=='order'"></order>-->
<!--        <user v-else></user>-->

<!--        使用動態元件-->
        <component :is="current"></component>
    </div>
</div>
</body>

<script>
    // 1 定義出 商品,訂單,使用者 三個元件
    Vue.component('goods', {
        template: `<div>
                        <h3>商品頁面</h3>
                        商品列表
                        <br>
                        商品列表
                    </div>`,
    })

    Vue.component('order', {
        template: `<div>
                        <h3>訂單頁面</h3>
                        訂單內容
                    </div>`,
    })

    Vue.component('user', {
        template: `<div>
                        <h3>使用者頁面</h3>
                        使用者資訊
                    </div>`,
    })

    var vm = new Vue({
        el: '#app',
        data: {
            current: 'goods'
        },
    })
</script>
</html>

3、內部元件keep-alive元件的使用

  • keep-alive 會把內部的元件進行快取,而不是銷燬元件;

  • 在使用 keep-alive 的時候,可以透過 include 指定哪些元件需要被快取;

  • 或者,透過 exclude 屬性指定哪些元件不需要被快取;但是:不要同時使用 include 和 exclude 這兩個屬性

<keep-alive exclude="goods">
     <component :is="current"></component>
</keep-alive>

五、插槽

1、介紹

slot的官方定義是用於元件內容分發,簡單通俗的解釋就是在元件化開發中,雖然元件是一樣的,但是在不同的使用場景,元件的某一部分需要有不同的內容顯示。slot就好比元件開發時定義的一個引數,如果不傳入值就當預設值使用,如果傳入了新值,在元件呼叫時就會替換定義時的slot預設值。

一般情況下,編寫完1個元件之後,元件的內容都是寫死的,需要加資料 只能去元件中修改,擴充套件性很差。然後就出現了插槽這個概念,只需在元件中新增<slot></slot>,就可以在body的元件標籤中新增內容。

2、匿名插槽

  • 匿名插槽插入不同的內容類似for迴圈一樣,使用插槽一次就要全部再來一遍,例如下面使用了兩個不同內容但是匿名插槽一樣,所以會有兩次完整的元件形成。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>

</head>
<body>
<div id="app">
    <h1>插槽使用</h1>
    <div>
        <Home style="background-color:greenyellow">
            <div>
                <img src="./img/1.jpg" alt="">
            </div>
        </Home>
    </div>
    <hr>
    <div>
        <Home style="background-color:orange">
            <div>
                <img src="./img/2.jpg" alt="">
            </div>
        </Home>
    </div>
</div>
</body>
<script>

    var vm = new Vue({
        el: '#app',
        data: {
            who: 'Home'
        },
        components: {
            Home: {
                template: `<div>
                                <h3>我是首頁</h3>
                                <slot></slot>
                                <h3>結束了</h3>
                        </div>`
            },
        }
    })
</script>
</html>

image

2、具名插槽

  • 在使用相同的具名插槽的時候,並沒有再次形成完整的元件內容,而是將插槽裡面的內容直接放到元件中對應插槽的位置
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./JS/vue.js"></script>
    <script src="./JS/axios.js"></script>
</head>
<body>
<div id="app">
    <h1>插槽使用</h1>
    <div>
        <Home style="background-color:greenyellow">
            <div slot="middle">
                <img src="./img/1.jpg" alt="">
            </div>
            <div slot="middle">
                <img src="./img/1.jpg" alt="">
            </div>
            <div slot="bottom">
                <a href="">點我看mm</a>
            </div>
        </Home>
    </div>
    <hr>
</div>
</body>
<script>

    var vm = new Vue({
        el: '#app',
        data: {
            who: 'Home'
        },
        components: {
            Home: {
                template: `<div>
                                <h3>我是首頁</h3>
                                <slot name="middle"></slot>
                                <h3>結束了</h3>
                                <slot name="bottom"></slot>
                        </div>`
            },
        }
    })
</script>
</html>

image

相關文章