這里不考慮ref的使用,通過ref的方式,可以解決大部分問題,但是就和寫html一樣,不到萬不得已你不會使用id,
而且極端場合下,如何給組件設置id,本身就是一個難題。
業務場景:
我們設計一個表單組件,需要用戶填寫年齡,因此有個輸入框,我們使用 v-model 綁定年齡字段,
顯然,年齡不能超過200,因此組件還必須給出校驗位,當年齡超過200,校驗位就置成false,
因為校驗位是在組件內部憑空產生的,父組件如何獲取校驗位就成了一個難題。
(表單不會只有1個輸入框,因此很難設置 ref )
方案1:實現v-model
簡單的實現方案,就是實現自定義組件的 v-model 功能,缺點就是 v-model 只能綁定一個值。
(當然,這個方案不適合前面提到的案例,你可以考慮綁定一個對象,而不是一個值,因此列為一種解決方案。)
方案2:傳遞對象
props使用Object類型,父組件將一整個對象傳遞給子控件,父子組件都可以對參數進行修改、取值。
以下面代碼為例,<data-table>組件的參數是一個Object類型,父子組件只要約定好參數中的內容即可。
這或許是最優解了,寫法上不會太過另類,而且,Vue也不會阻止子組件修改Object的字段值。
感覺上,這種做法似乎有些脫離了Vue設計初衷,Vue不會阻止子組件修改Object參數的內容,
同時,Vue 不會主動偵聽 Object 字段的變化,最直接的問題,就是頁面數據可能不發生聯動了,
不過即便不聯動,使用watch、computed也能解決問題,辦法總比困難多,主要也看編程如何取舍了。
<template xmlns="http://www.w3.org/1999/html"> <data-table :table="table"> </data-table> </template> <script> import DataTable from '@/components/widget/DataTable.vue' export default { components: { DataTable }, data() { return { table: { //分頁配置 url: undefined , page: 1 , limit: 10 , enabledSelection: true , resultParser: undefined , data: [{ date: '2016-05-02', name: '王小虎', address: '上海市普陀區金沙江路 1518 弄', isDisabled: false, select: 1, image: 'http://www.baidu.com' }] } } } } </script>
方案3:使用provide
與方案2基本一致,不過不用props,而是使用provide,也是將一整個對象傳遞給子控件。
兩種做法,應用場景有些不同。
案例:
可以參考 element-ui 的 table 設計,table 和 column 一般會在代碼中同時出現,
我們只把數據傳遞給了 table 組件,但是 column 明顯也獲取了我們的數據,
我們並沒有看到 table 將數據傳遞給 column。
其他人看不到父子組件之間傳遞參數,但是子組件確確實實獲得了父組件的參數,
如果也希望設計這樣的組件,這時候就要用到 provide,provide 能起到暗度陳倉的效果,悄悄地就把參數傳給了子組件。
父級控件
通過provide,將自己的參數傳遞到子級控件。
<script> import FormInput from './FormInput.vue' export default { name: "fast-form" , provide() { return { formGroup: this.formGroup }; } } <script>
子級控件
通過inject接收父級傳遞的參數。
<script> export default { name: "form-input" , inject: ['formGroup'] , created: function () { //給formGroup增加一個事件回調,此處不符合VUE數據單向數據流的設計要求,但是滿足普通JS語法 let currentWidget = this; for (let i = 0; i < currentWidget.formGroup.length; i++) { if (currentWidget.formGroup[i].name === this.name) { currentWidget.formGroup[i].isValid = function () { return currentWidget.checkFormInputValidity(); } } } }, methods: { /** * 比較當前值是否有效 */ checkFormInputValidity: function (value) { } } } <script>
