iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 2
1
自我挑戰組

三十天用Vue.jS打造一個網路商城系列 第 2

Day2:如何不用VueJS實現雙向數據綁定?

  • 分享至 

  • xImage
  •  

閱讀前,建議先參考Day:1閱讀指南&為何選擇這個題目,再來考慮是否花時間閱讀

▌挑戰簡介

  • 題目:三十天用Vue.jS打造一個網路商城

  • 挑戰內容:利用慕課網(IMOOC)的「Vue2.0+Node.js+MongoDB 全棧打造商城系統」的課程嘗試在30天內打造網路商城。

  • 適合閱讀者:有VueJS基礎的人

  • 不適合閱讀者:沒有VueJS基礎的人(因為我省略很多前提)

  • 警告:我只是Vue的初學習者,肯定會有錯誤,歡迎指出!

▌輸入、顯示同步的效果

以下功能應該很常見,就是在輸入框中輸入aaaa,也可以同步顯示aaaa

我想這個是學習VueJS的人,第一次學會做出的效果。

可是,我們可以不用VueJS就實現這個功能嗎?可以

▌如何不用Vue.Js做出類似效果

只要在input的DOM上加事件監聽事件,讓input只要測到keyup鍵盤事件發生時,就自動把輸入的value傳到display的innerHTML中

<body>
    <input type="text" id="input">
    <br>
    <br>
    <span id="display"></span>
</body>
<script>
    // 一個添加物件屬性的函式
    document.getElementById("input").addEventListener("keyup", function (event) {
        document.getElementById("display").innerHTML = event.target.value;
    })
</script>

可是,這頂多只能稱為單向數據綁定,因為我們不能用其他方式反向去操縱input中的value

▌Object.defineProperty()

首先介紹,Object.defineProperty()這個函式

Object.defineProperty()這個函式可以改變物件屬性及其value

比如說,假設我們有一個obj物件

//創建一個obj物件,然後附上context屬性,其value為hi~~~
var obj = {
       context: "hi~~~"
   }
   
console.log(obj)   //回傳{context: "hi~~~"}

這時候想要改變obj的context屬性內容有幾種做法

obj.context="nice to meet you"
console.log(obj)    //回傳{context: "nice to meet you"}

或是也可以用Object.definePropert()

Object.defineProperty(obj, "context", {
        value: "nice to meet you"  //回傳{context: "nice to meet you"}
   })

所以勒,那幹嘛用Object.defineProperty?而且這個數據雙向綁定有什麼關係?

因為 Object.defineProperty()有一個set()函式可以用,當他偵測到obj屬性內容被更改時就會被觸發,因此可以做一些事情。

Object.defineProperty(obj, "context", {
        set() { //當有人嘗試更改obj.context的內容時就會觸發console.log()
            console.log("討厭,想偷改我的內容>.<")
        }
    })

▌開始來嘗試做雙向數據綁定

了解這個set()後,就可以用來做雙向數據綁定

<body>
    <input type="text" id="input">
    <br>
    <br>
    <span id="display"></span>
</body>
<script>
    var obj = {
    }


    Object.defineProperty(obj, "context", {
        set(val) {   //當有人嘗試更改obj.context的內容時就會觸以下事件
            document.getElementById("input").value = val   
            //把obj.context被更改的新值傳入輸入框(input)
            document.getElementById("display").innerHTML = val
            //把obj.context被更改的新值傳入顯示區(display)
        }
    })
    
        document.getElementById("input").addEventListener("keyup", function (event) {
        obj.context = event.target.value;
    })  //當輸入框(input)內容被輸入value時,也會把 obj.context改變為value
   

![](https://media.giphy.com/media/3Nr88xdKfAdRgU3aKO/giphy.gif

綜上所述,只要運用addEventListener()Object.defineProperty(),其實不需要Vue.JS也可以實現雙向數據綁定

  • 當輸入框(input)的value改變時,就會改變object的值
  • 當object的值改變時,也會改變輸入框(input)和顯示區(display)的值

恩...是不是跟Vue.JS很像呢!!!沒錯,因為VueJS的雙向數據綁定就是這樣實現的

▌奇怪的Bug

好吧,雖然我說這樣可以完成雙向數據綁定,但其實我並沒有做成功。我雖然透過操作object成功改變了input的值。但當我更改輸入框(input)的value時,卻導致object.context變成了undefined
有沒有人知道為什麼會這樣呢XD?(請參考以下GIF圖檔)

▌參考資料

  • 大陸慕課網(IMOOC)的「Vue2.0+Node.js+MongoDB 全棧打造商城系統」

上一篇
Day1:閱讀指南&為何選擇這個題目?
下一篇
Day3:VueCli是什麼?怎麼安裝VueCli
系列文
三十天用Vue.jS打造一個網路商城30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
ayugioh2003
iT邦新手 1 級 ‧ 2019-11-07 19:04:41

感謝教學
Vue 如何雙向綁定資料的機制這塊講得滿好懂的 ~

BTW

好吧,雖然我說這樣可以完成雙向數據綁定,但其實我並沒有做成功。我雖然透過操作object成功改變了input的值。但當我更改輸入框(input)的value時,卻導致object.context變成了undefined

我想了一下,這個問題可能是 set() 內沒有把 obj.context 的值放到某個地方儲存,也沒有用 get() 設定告知 obj.context 要去哪邊求值後返回而導致

以下是我修改後的 code

let obj = {} // 空殼,取值與設定值的過程會被 defineProperty 介入
let _obj = {} // 存放實際值的地方

Object.defineProperty(obj, "context", {
  set(val) { 
    document.getElementById("input").value = val   
    document.getElementById("display").innerHTML = val
    _obj.context = val // 將 context 實際值放到 _obj 中
  },
  get() {
    return _obj.context // 返回 _obj 中的 context 實際值
  }
})

document.getElementById("input").addEventListener("keyup", function (event) {
  obj.context = event.target.value;
  // console.log(event.target.value)
})

附上 codepen
https://codepen.io/ayugioh2003/pen/vYYjWqe?editors=1011

我要留言

立即登入留言