首先把上節課實現的tree的邏輯進行封裝,封裝成一個組件,能夠達到一個復用的效果。
第二部門增加一個操作目錄,每個目錄,每個文件都應該可以操作,比如刪除這個文件,重命名這個文件的文件名或者目錄,
3.在這個組件里面傳入多個值,而且每次做更新會同時更新這多個值,如果一個值在組件內需要更新的話, 我們可以用v-model,如果多個值呢?我們來學習一下替代方案。
最后給這個組件完善一下,增加一些鈎子函數。來滿足我們實際業務中的需求。
開始
首先我們要把這個tree封裝成一個組件,創建folder-tree這個組件,
index.js內,先導出去
這個地方,我們只用一個tree組件。
給這個組件一個name值
之前的tree組件我們只傳入了轉換為樹狀數據的data數據,然后傳進去了一個render函數。
我們現就要把它作為屬性傳給folder-tree組件了。引入folderTree,然后注冊這個組件,並使用這個組件。
我們之前傳入的數據是轉換后的,整理好的樹狀的數據,實際我們把它封裝成一個組件,那么我應該在用的時候,盡量的減少我們自己的再做的操作,要不然這些東西都在這里做的話,就沒有必要在封裝了。封裝的目的就是為了在復用的時候減少我們的工作,
所以我們直接傳入folderList文件夾的列表數據和文件的列表數據,在組件內不讓它去做轉換。
轉換的數據就是我們傳遞進來的屬性。
內部定義 folderTree
res[0]是文件夾數組,res[1]是文件數組。
把之前的render函數賦值到組件內部
復制到了組件的內部
樣式剪切到組件的內部
剪切到了組件的內部
聲明周期mouted鈎子函數內,先調用一次,如果這個時候傳進來有數據,在這里就會做這個工作。
如果一開始沒有,是異步的傳進來的數據呢?所以我們要監聽folderList和fileList變化的時候,都要做處理。
和之前的效果一樣

操作目錄
接下來,來看操作目錄這塊。
我們要在render的這個地方,給每個元素都加一個下拉菜單。
下拉菜單用Dropdown這個組件。里面第一個元素是用來,顯示下拉列表的元素。在jsx里面,view的組件必須用帶前綴i-的方式

復制過來是大寫的Icon。

我們要改成小寫的方式

給它設置一個size,我們的size是一個數值類型,不是字符串的類型, 所以這里我們要用花括號括起來


每一條都這么寬,想讓button始終顯示在最右側

要不然文件名,不一樣長就對不齊了。給它加一個class屬性


沒有效果,因為它外層裹了一個ivu-dropdown

tree-item里面直接子元素的 .ivu-dropdown


定義里面的列表
用dropdownMenu讓它作為一個插槽。
移出來,和i-button是同級別的。
鼠標放上拉顏色怪怪的,背景是灰色,並且寬度沒有100%的背景色。可能是被我們tree里面的一些樣式給覆蓋了。
樣式被覆蓋,需要我們自己寫一下樣式。設置了 下面的css ,沒有效果
應該還是一些樣式的權重不夠。看到這個ul的padding-left還是有的
勾選去掉就可以了
我們給這個ul加類名ivu-dropdown-menu
item同理也加上類名為ivu-dropdown-item,這樣樣式就正常了。
定義兩個屬性,一個是文件夾操作列表,一個是文件操作列表。這里沒有設置默認值,如果是空數組的話,說明它不需要下拉菜單,所以之類我們沒有設置默認值,直接讓它是一個aarray類型,到時候直接是否為空就直接判斷這個數組是否是undefined,如果是undefined說明它沒有傳入值。
沒有傳dolerDrop沒有傳就直接不顯示這個dropdown按鈕了。
調用組件的時候,傳入這兩個屬性
渲染傳進來的菜單。對dropList做一個映射。return里面寫我們jsx的內容。
綁定一個name屬性,方便我們后面知道點擊了是哪一個
為了區分開,把菜單的名稱改一下
dropdown設置右邊頂部對齊。
頁面寬度比較窄的時候會顯示在左側,
根據屏幕的邊緣智能判斷,顯示在那一邊
dropdown添加事件
dropdown有個on-click事件
在jsx里面我要用on-前綴來標識,這是一個綁定的事件,事件名寫在后面
點擊刪除文件夾
點擊重命名,顯示輸入框,輸入新的名字
重命名
首先要有一個全局的標識。
方法需要綁定參數,用bind在this上面去綁定
click事件原生返回的name值,它會拼在我們自定義的參數 后面
所以這里我們第一個參數是data,第二個參數是name
直接還可以再簡寫一下。如有這個data.type字段的話就用folder。,沒有的話就用file
有個這個標識之后,我們就可以判斷了。如果當前編輯的id等於拼接的id那么,
那么就顯示i-input,同時給i-input綁定上input事件,
定義方法,它的參數就是當前修改后的內容
定義變量currentRenamingContent
點擊重命名
文本框后面,還需要兩個按鈕,這里因為jsx里面要求只有一個根節點,所以用一個span標簽包裹起來。
加上兩個按鈕,然后輸入框 讓他短一點,加上一個class類名
這里還是用計算的屬性,100%減去80px
按鈕設置為small 並且類型是texxt
點擊重命名
把狀態抽到上面
如果正在重名,那么dropDown也不顯示
保存修改事件
點擊對號以后,要替換原來的內容
還是需要把data參數傳進來
接下里要在里面遍歷一下,如果你當前修改的是文件夾目錄中的一個目錄的名字的話,你是要遍歷文件夾列表。
定義i為-1, 如果type類型是folder的話,也就是文件夾
獲取文件list的長度,然后循環,如果當前的item的id等於修改的id,那么就把item的name替換為修改的內容。並且用splice方法把文件夾list的item元素移除,再替換修改后的進來。
如果是文件列表的話。下面就是循環fileList
把這部分抽離出來封裝成一個公共的方法,下面調用的時候 直接傳參數list進去就可以了。
讓文本框消失
事件綁定錯了值了,綁定到了差號上了。移動到對號上
缺點,我們直接在這個組件內修改filstList和folderList肯定是不行的
修改父組件內的值
引入深拷貝
修改沒有效果
先把修改后的值return 出來先
通過事件拋到父組件內去修改。在父組件內,我們綁定了兩個值,一個folder-list一個是file-list .如果只綁定一個值的話 ,我們可以用v-model來做,但是我們這里綁定了兩個值。
這里我們用之前講過的.sync修飾符。父組件間內,這里都加上sync修飾符。
子組件內怎么更新呢?update冒號 這是固定的。
然后要更新哪個值,folderList是父組件傳過來的值。
修改文件同理
這里是拿到了name賦值給title,所以我們修改了name的值 也是可以的。
同時這里監聽了兩個list的變化,一但有變化就重新觸發 轉換的方法,上面把name賦值給title,所以我們修改的時候修改的name值也是對的。
刪除操作
刪除要提醒用戶,是否要刪除
封裝一個方法,判斷是刪除文件夾還是文件。
然后下面判斷是文件夾還是文件。
確定要刪除執行的方法
判斷是否是文件夾,如果是文件夾,那么更新的就是folderList,如果是文件更新的就是fileList了。
判斷要刪除的是哪個對象, 就深拷貝哪個對象
刪除操作可以使用filter過濾操作,return的就是不需要過濾掉的,就是你要的
返回的是id不等於當前要刪除的id的。那就是刪了以后剩下的元素。
emit事件
刪除后,文件夾就合住了 需要重新打開。這樣體驗就很不好。
刪除后,文件夾保持展開的狀態
tree組件要給當前的這個item一個屬性,設置一個值,是否展開子節點,如果設置為true就會展開這一節
需要一個方法,傳入一個id。你要展開哪一個目錄,就把文件夾id傳進去。
在util里封裝一個方法。用map方法做一個映射。
如果是文件夾,並且找到了這個id。那么就展開這個節點
如果item.children里面有一個children的expand為true的話 那么就返回。
所以這里的判斷就是判斷這個點的子節點有一個是展開的。那么就展開當前這個節點。
否則就不展開。
最后返回當前的item
最后把返回的新數組 return出去
在組件內使用一下
調用展開的方法
沒起作用
放在this.$nextTick里面執行試一下
有效果了
剛才沒起作用的原因:可能是刪除之后,視圖還沒有更新完 我們就去展開這節點,所以有問題 。
鈎子函數
前端刪除了,但是后端的服務刪除報錯了。那么這樣前后端的數據就不一致。
所以點擊刪除 ,應該先去調用接口去做刪除操作。刪除成功了再往下繼續。
這里就引入鈎子函數。
返回一個Promise。這里我們寫的是promise,實際的開發過程中,應該調用的是一個接口。這里我們暫時用Promise來代替。
模擬一個數據的延遲2秒后 成功返回。
組件內接收,方法
默認可以不設置。不設置的話,就是你比較有信心,不需要這樣的一個鈎子。
如果有這個函數。那么后面的操作都放在這個函數的then里面。
報錯了就提示一下
把展開操作移到上面去
folderId也移到上面去。
我們現在錯誤設置的為null。那就是沒有錯誤
2秒后成功刪除
這里改成錯誤的
本節代碼
結束