Maison  >  Article  >  interface Web  >  Comment utiliser les classes ES6 pour imiter Vue et écrire une liaison bidirectionnelle

Comment utiliser les classes ES6 pour imiter Vue et écrire une liaison bidirectionnelle

php中世界最好的语言
php中世界最好的语言original
2018-06-02 15:36:381232parcourir

Cette fois, je vais vous montrer comment utiliser les classes ES6 pour imiter Vue pour écrire une liaison bidirectionnelle Quelles sont les précautions et voici des cas pratiques.

L'effet final est le suivant :

Constructeur (constructeur)

Construit un objet TinyVue, y compris éléments de base, données, méthodes

class TinyVue{
 constructor({el, data, methods}){
  this.$data = data
  this.$el = document.querySelector(el)
  this.$methods = methods
  // 初始化
  this._compile()
  this._updater()
  this._watcher()
 }
}

Compilateur (compiler)

est utilisé pour analyser les modèles V liés aux zones de saisie et aux listes déroulantes et clique sur éléments événement@clic.

Créez d'abord une fonction pour charger les événements :

// 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)
  }
 })
}

Charger l'événement de la zone de saisie

this._initEvents('input, textarea', 'v-model', (i, key) => {
 i.addEventListener('input', () => {
  Object.assign(this.$data, {[key]: i.value})
 })
})

Charger l'événement de la zone de sélection

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

Charger événement click

L'événement click correspond à l'événement dans les méthodes

this._initEvents('*', '@click', (i, key) => {
 i.addEventListener('click', () => this.$methods[key].bind(this.$data)())
})

View updater (updater)

Identique à First, créez un public fonction pour gérer les vues dans différents éléments, y compris la valeur de input et textarea, la valeur de sélection de select, p's innerHTML

_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)
  }
 })
}

mettre à jour la vue de la zone de saisie

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

Mettre à jour la sélection box view

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')
 })
})

Mettre à jour innerHTML

La méthode d'implémentation ici est un peu faible, je ne pense qu'au remplacement régulier {{text}}

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])
  })
 }
})

auditeur (observateur)

Mettre à jour la vue après des modifications de données

<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>

Tout le code de TinyVue

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}))
  })
 }
}

Je crois que vous maîtrisez la méthode après lire le cas dans cet article, et plus encore Comme c'est excitant, veuillez prêter attention aux autres articles connexes sur le site Web chinois de php !

Lecture recommandée :

Comment utiliser Vue pour implémenter un bouton de compte à rebours

Comment utiliser Vue pour écrire des données bidirectionnelles reliure

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn