Vue之合理划分容器組件與展示組件
如果要將 Vue 組件按照職能划分,我們可以將其分為兩種類型:容器組件和展示組件。
容器組件和展示組件的概念來自於 Redux 文檔,那么首先什么是容器組件呢?顧名思義,它是一個容器性質的組件,我們可以把它理解為最外層的父組件,也就是最頂層的組件,一般我們把它放置在 views 文件夾下,其功能主要用於做數據提取與實現公共邏輯,然后渲染對應的子組件
另一類組件叫做展示組件,字面意思就是主要用於做展示的組件,其主要功能是負責接收從容器組件傳輸過來的數據並在頁面上渲染,實現其內部獨有的功能邏輯
一個頁面中容器組件與展示組件的關系如下圖所示
上圖我們以博客首頁為例,容器組件就是整個首頁最外層的父組件,而展示組件就包含了導航欄、文章列表、底部等子組件,代碼層面如下
<template> <div> <navigation @count="countFn"></navigation> <article :list="articleList"></article> <foot></foot> </div> </template> <script> import { mapActions, mapGetters } from 'vuex'; export default { mounted() { this.SET_BLOG_DATA(); // 調用接口獲取數據 }, computed: { ...mapGetters(['articleList']), // 監聽 state } methods: { ...mapActions(['SET_BLOG_DATA', 'SET_NAV_COUNT']), countFn(item) { // 調用接口存儲導航點擊次數並跳轉,通過派發 action 的形式來發起 state 變化 this.SET_NAV_COUNT({ type: item.type }); this.$router.push({name: item.route}); } } } </script>
以上是首頁容器組件中的主要代碼,其主要做了兩件事情:數據的傳遞和回調的處理,當然還可以包括處理一些該頁面中不屬於任何一個展示組件的方法,比如校驗登錄狀態。在一個容器組件中可以包含多個展示組件,下面我們來看一下展示組件 Navigation 中的代碼
<template> <ul> <li v-for="(item, index) in nav" :key="index" @click="goNav(item)" v-text="item.name" ></li> </ul> </template> <script> export default { data() { return { nav: [{ name: '首頁', route: 'index', type: 'index' }, { name: '文章', route: 'article', type: 'article' }, { name: '關於', route: 'about', type: 'about' }] } }, methods: { goNav(item) { this.$emit('count', item); // 觸發回調 } } } </script>
Navigation
導航組件只負責自己內部的數據渲染和回調邏輯,對於存儲每個導航的點擊量及跳轉邏輯來說,作為展示組件這並不是其所關心的,所以我們需要通過觸發容器組件回調的方式來實現。再來看一下展示組件 Article 的代碼
<template> <ul> <li v-for="(item, index) in list" :key="index" @click="goPage(item.id)" v-text="item.title" ></li> </ul> </template> <script> export default { props: { // 接收容器組件數據 list: { default: [], type: Array } } } </script>
展示組件 Article 中動態的數據通過 props 從父組件中獲取,其內部只處理文章列表的渲染工作,這樣很好的將 UI 層面和應用層面進行了分離,便於今后該組件的復用。
此外 Foot 組件為純靜態組件,其只負責內部數據的渲染,不接收外部的數據和回調方法,這里就不做介紹了。
組件的層次結構
了解了組件職能的划分后,我們再來看一下組件的層次結構。關於組件的層次,一般頁面中不宜嵌套超過 3 層的組件,因為超過 3 層后父子組件的通信就會變得相對困難,不利於項目的開發和維護。3 層結構的容器組件與展示組件的數據傳遞如下
可見組件的層次越深數據傳遞的過程就會變得越復雜,當然這取決於你如何划分容器組件和展示組件,比如我們可以將上述博客首頁換一種划分方式
上圖我們頁面中存在 3 個容器組件,每個容器組件又可以包含各自的展示組件,這樣一定程度上可以減少組件的層次嵌套深度。當然展示組件中也可以包含對應的容器組件來解決數據傳輸的問題
這樣展示組件 B 下面的容器組件 C 便可以不依賴於容器組件 A 的數據,其可以單獨的進行數據獲取和狀態更新