Vue input文字框v-model與ref.value不能同時使用賦值,如何實現操作節點方式賦值?

崔迪的傻大貓發表於2020-12-21

我們開發時有是會遇到這樣一個場景,點選某一個文字框,蹦出彈窗,裡面是一系列的表格,勾選表格項,將其指定的內容賦值到對應的我們點選的那個文字框上。

如下 需求
在這裡插入圖片描述
現在有兩個文字框,當我們點選時讓其蹦出彈窗,內容123變成abc。
在這裡插入圖片描述
我們可以看到,兩個對應的v-model值已經繫結到了對應的文字框上面。

  methods: {
    proup(dom) {
      let vm = this
      // Dialog是vant的彈窗 
      Dialog.alert({
        title: '我是一個彈窗',
        message: '我要給其對應的內容進行賦值',
      }).then(() => {
         vm.form.inp = 'abc'
         console.log('我完成了賦值')
      })
    },
  },

在這裡插入圖片描述
在這裡插入圖片描述
此時我們可以看到,當我們勾選確定時對應的123也就隨機變成了abc,我們此時可以看到對應的值是寫死的
vm.form.inp1=‘abc’
並不是說我們想要去點選哪一個,哪一個的值就會變
那麼如何實現對應的功能呢?
其實我們在@click點選事件時就已經傳遞了對應的值,我們可以根據對應的值去進行判斷

  methods: {
    proup(dom) {
      let vm = this
      // Dialog是vant的彈窗 
      Dialog.alert({
        title: '我是一個彈窗',
        message: '我要給其對應的內容進行賦值',
      }).then(() => {
        if (dom == 'inp1') {
          // 給inp1進行賦值
          vm.form.inp1 = 'abc'
        } else if (dom == 'inp2') {
          vm.form.obj.inp2 = 'abc'
        }
      })
    },
  },

當然這樣好嗎?如果我們只有一個或者兩個文字框的話可以採用這種方式,但注意如果後續我們新增需求,新增條件的話,肯定會造成程式碼的高度耦合,並且繁瑣不好維護,我們能不能就是用另一種方法實現此功能呢?

思路1、ref方式,操作dom,變更dom的value實現功能

首先一定會有人問了為什麼要用ref呢?用ref的需求是什麼,我直接給那個對應點選的設定一下不行嗎?event?事件物件?其實我們可以嘗試一下。

    proup(e,dom) {let vm = this
      Dialog.alert({
        title: '我是一個彈窗',
        message: '我要給其對應的內容進行賦值',
      }).then(() => {
        // vm.form.inp = 'abc'
        // console.log('我完成了賦值')
        // 如果現在的需求是,點選哪一個給哪一個賦值,我想給form.obj.inp2進行賦值呢?
        // 其實第一想到的就是if else進行判斷,我們在事件觸發時來進行判斷當前點選的是哪一個,點選的是哪一個,我們給哪一個進行賦值
        if (dom == 'inp1') {
          // 給inp1進行賦值
          // vm.form.inp1 = 'abc'
          e.path[0].value ='abc' // 當然e.target.value 也同樣是可以的
          console.log(vm.form.inp1)
        } else if (dom == 'inp2') {
          vm.form.obj.inp2 = 'abc'
        }
      })
    },

在這裡插入圖片描述

我們可以看到在上方我呼叫了事件物件,獲取到了當前點選的節點,並且我們可以獲取到當前點選的文字框,但是我們需要注意的一點是什麼,值可以更改,但是v-model對應繫結的值是不可以更改的,

其實很簡單的一個邏輯

v-model是雙向繫結,學過vue的同學大家對其都會有一個簡單的概念,但是大家要記住,他底層是如何實現的呢?

簡單的來說 他是 :value與 @input事件的結合體

我們可以看一下oninput事件是如何觸發的

input:當文字框的值發生改變、存在焦點時(實時更新),會觸發 input事件。

回過頭來我們就可以順通這個邏輯 為什麼節點的value值已經變了,但是v-model的值卻沒有變更,因為這個事件本身是沒有進行觸發的

如果想要讓其值進行變更的話那麼怎麼樣實現呢,其實順著這個input事件,那麼我們讓其獲取焦點不就完了嗎?
在這裡插入圖片描述
看結果
在這裡插入圖片描述
其實我們可以看到,對應的焦點是在的,value的值也同樣變更了的,但是form中對應v-model繫結的inp1值並沒有改變

所以從邏輯上來說 文字變更+獲取焦點 /= Input事件

那麼如何實現功能呢?
回到我們上面說的ref,其實轉過來說ref其實也就事件物件的方式

在這裡插入圖片描述
我們可以看到這個時候控制檯已經報錯,雖然v-model值已經變更,但是會報子元件更改prop的錯誤,爆紅,那當然是行不通的。
在這裡插入圖片描述

那麼現在我們需不需要另闢途徑呢?注意,我們上方說到的,v-model的原理是什麼 :value和@input事件,那麼我們手動的使用js呼叫一次input事件不就可以了嗎?

我們可以這樣 使用事件物件

      Dialog.alert({
        title: '我是一個彈窗',
        message: '我要給其對應的內容進行賦值',
      }).then(() => {
        // vm.form.inp = 'abc'
        // console.log('我完成了賦值')
        // 如果現在的需求是,點選哪一個給哪一個賦值,我想給form.obj.inp2進行賦值呢?
        // 其實第一想到的就是if else進行判斷,我們在事件觸發時來進行判斷當前點選的是哪一個,點選的是哪一個,我們給哪一個進行賦值
        if (dom == 'inp1') {
          // 給inp1進行賦值
          // 讓其獲取焦點是不是就可以實現了呢?
          e.target.value = 'abc'
          // 手動呼叫input事件
          e.target.dispatchEvent(new Event('input'))
        } else if (dom == 'inp2') {
          vm.form.obj.inp2 = 'abc'
        }
      })

在這裡插入圖片描述

我們可以看到對應的文字框就已經變成對應的值,並且v-model的值也已經進行了改變

另一種解題思路

通過引數傳遞,來實現功能
在這裡插入圖片描述
js程式碼

    proup(e, dom) {
    // 定義獲取對應的物件,forEach進行迴圈遍歷
      let ele = this.form
      dom.forEach((element,index) => {
      // 判斷當前的index索引是不是引數的最後一項
        if(index == dom.length -1){
        // 如果是最後一項相當於是物件之前了,最後一個了,物件賦值
          ele[element] = 'aaa'
        }else{
        // 否則向下遞迴 接著讓其等於物件,就像inp2一樣
          ele = ele[element]
        }
      })
      }

在這裡插入圖片描述
在這裡插入圖片描述
此時功能即實現。

相關文章