ホームページ > ウェブフロントエンド > jsチュートリアル > ES6 クラスを使用して Vue を模倣し、双方向バインディングを作成する方法

ES6 クラスを使用して Vue を模倣し、双方向バインディングを作成する方法

php中世界最好的语言
リリース: 2018-06-02 15:36:38
オリジナル
1368 人が閲覧しました

今回は、ES6 クラスを使用して Vue を模倣して双方向バインディングを記述する方法を説明します。 ES6 クラスを使用して Vue を模倣して双方向バインディングを記述するための 注意事項 は何ですか。見てみましょう。

最終的な効果は次のとおりです:

Constructor (コンストラクター)

基本的な el、データ、メソッドを含む TinyVue オブジェクトを構築します

1

2

3

4

5

6

7

8

9

10

11

class TinyVue{

 constructor({el, data, methods}){

  this.$data = data

  this.$el = document.querySelector(el)

  this.$methods = methods

  // 初始化

  this._compile()

  this._updater()

  this._watcher()

 }

}

ログイン後にコピー

Compiler (コンパイル)

は、入力ボックスとドロップダウン ボックスの v-model と要素のクリック イベント @click にバインディングします。

まずイベントをロードする関数を作成します:

1

2

3

4

5

6

7

8

9

// el为元素tagName,attr为元素属性(v-model,@click)

_initEvents(el, attr, callBack) {

 this.$el.querySelectorAll(el).forEach(i => {

  if(i.hasAttribute(attr)) {

   let key = i.getAttribute(attr)

   callBack(i, key)

  }

 })

}

ログイン後にコピー
入力ボックスイベントをロード

1

2

3

4

5

this._initEvents('input, textarea''v-model', (i, key) => {

 i.addEventListener('input', () => {

  Object.assign(this.$data, {[key]: i.value})

 })

})

ログイン後にコピー
選択ボックスイベントをロード

1

2

3

this._initEvents('select''v-model', (i, key) => {

 i.addEventListener('change', () => Object.assign(this.$data, {[key]: i.options[i.options.selectedIndex].value}))

})

ログイン後にコピー
クリックイベントをロード

クリックイベントはメソッドのイベントに対応します

1

2

3

this._initEvents('*''@click', (i, key) => {

 i.addEventListener('click', () => this.$methods[key].bind(this.$data)())

})

ログイン後にコピー

ビューアップデータ(updater)

同様に、最初に、input、textarea 値、select value、p の innerHTML などのさまざまな要素のビューを処理するパブリック関数を作成します

1

2

3

4

5

6

7

8

9

_initView(el, attr, callBack) {

 this.$el.querySelectorAll(el, attr, callBack).forEach(i => {

  if(i.hasAttribute(attr)) {

   let key = i.getAttribute(attr),

    data = this.$data[key]

   callBack(i, key, data)

  }

 })

}

ログイン後にコピー
入力ボックス ビューを更新

1

2

3

this._initView('input, textarea''v-model', (i, key, data) => {

 i.value = data

})

ログイン後にコピー
選択ボックス ビューを更新

1

2

3

4

5

6

this._initView('select''v-model', (i, key, data) => {

 i.querySelectorAll('option').forEach(v => {

  if(v.value == data) v.setAttribute('selected', true)

  else v.removeAttribute('selected')

 })

})

ログイン後にコピー
innerHTML を更新

ここでの実装方法は少し低めで、定期的な置き換えしか考えていません{{text}}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

let regExpInner = /\{{ *([\w_\-]+) *\}}/g

this.$el.querySelectorAll("*").forEach(i => {

 let replaceList = i.innerHTML.match(regExpInner) || (i.hasAttribute('vueID') && i.getAttribute('vueID').match(regExpInner))

 if(replaceList) {

  if(!i.hasAttribute('vueID')) {

   i.setAttribute('vueID', i.innerHTML)

  }

  i.innerHTML = i.getAttribute('vueID')

  replaceList.forEach(v => {

   let key = v.slice(2, v.length - 2)

   i.innerHTML = i.innerHTML.replace(v, this.$data[key])

  })

 }

})

ログイン後にコピー

Listener (watcher)

データ変更後にビューを更新

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

<p id="app">

 <input type="text" v-model="text1"><br>

 <input type="text" v-model="text2"><br>

 <textarea type="text" v-model="text3"></textarea><br>

 <button @click="add">加一</button>

 <h1>您输入的是:{{text1}}+{{text2}}+{{text3}}</h1>

 <select v-model="select">

  <option value="volvo">Volvo</option>

  <option value="saab">Saab</option>

 </select>

 <select v-model="select">

  <option value="volvo">Volvo</option>

  <option value="saab">Saab</option>

 </select>

 <h1>您选择了:{{select}}</h1>

</p>

<script src="./TinyVue.js"></script>

<script>

 let app = new TinyVue({

  el: '#app',

  data: {

   text1: 123,

   text2: 456,

   text3: '文本框',

   select: 'saab'

  },

  methods: {

   add() {

    this.text1 ++

    this.text2 ++

   }

  }

 })

</script>

ログイン後にコピー
TinyVue all code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

class TinyVue{

 constructor({el, data, methods}){

  this.$data = data

  this.$el = document.querySelector(el)

  this.$methods = methods

  this._compile()

  this._updater()

  this._watcher()

 }

 _watcher(data = this.$data) {

  let that = this

  Object.keys(data).forEach(i => {

   let value = data[i]

   Object.defineProperty(data, i, {

    enumerable: true,

    configurable: true,

    get: function () {

     return value;

    },

    set: function (newVal) {

     if (value !== newVal) {

      value = newVal;

      that._updater()

     }

    }

   })

  })

 }

 _initEvents(el, attr, callBack) {

  this.$el.querySelectorAll(el).forEach(i => {

   if(i.hasAttribute(attr)) {

    let key = i.getAttribute(attr)

    callBack(i, key)

   }

  })

 }

 _initView(el, attr, callBack) {

  this.$el.querySelectorAll(el, attr, callBack).forEach(i => {

   if(i.hasAttribute(attr)) {

    let key = i.getAttribute(attr),

     data = this.$data[key]

    callBack(i, key, data)

   }

  })

 }

 _updater() {

  this._initView('input, textarea''v-model', (i, key, data) => {

   i.value = data

  })

  this._initView('select''v-model', (i, key, data) => {

   i.querySelectorAll('option').forEach(v => {

    if(v.value == data) v.setAttribute('selected', true)

    else v.removeAttribute('selected')

   })

  })

  let regExpInner = /\{{ *([\w_\-]+) *\}}/g

  this.$el.querySelectorAll("*").forEach(i => {

   let replaceList = i.innerHTML.match(regExpInner) || (i.hasAttribute('vueID') && i.getAttribute('vueID').match(regExpInner))

   if(replaceList) {

    if(!i.hasAttribute('vueID')) {

     i.setAttribute('vueID', i.innerHTML)

    }

    i.innerHTML = i.getAttribute('vueID')

    replaceList.forEach(v => {

     let key = v.slice(2, v.length - 2)

     i.innerHTML = i.innerHTML.replace(v, this.$data[key])

    })

   }

  })

 }

 _compile() {

  this._initEvents('*''@click', (i, key) => {

   i.addEventListener('click', () => this.$methods[key].bind(this.$data)())

  })

  this._initEvents('input, textarea''v-model', (i, key) => {

   i.addEventListener('input', () => {

    Object.assign(this.$data, {[key]: i.value})

   })

  })

  this._initEvents('select''v-model', (i, key) => {

   i.addEventListener('change', () => Object.assign(this.$data, {[key]: i.options[i.options.selectedIndex].value}))

  })

 }

}

ログイン後にコピー
この記事の事例を読んでその方法をマスターした方は、さらに興味深い情報については、PHP 中国語 Web サイトの他の関連記事に注目してください。

推奨読書:

Vue を使用してカウントダウン ボタンを実装する方法

Vue を使用して双方向データ バインディングを作成する方法

以上がES6 クラスを使用して Vue を模倣し、双方向バインディングを作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート