Heim >Web-Frontend >js-Tutorial >Verwenden Sie ES6-Klassen, um Vue zu imitieren und ein Beispiel für eine bidirektionale Bindung zu schreiben
In diesem Artikel wird hauptsächlich die Verwendung von ES6-Klassen zum Nachahmen von Vue beschrieben, um einen Beispielcode für die Zwei-Wege-Bindung zu schreiben. Ich werde ihn jetzt als Referenz verwenden.
In diesem Artikel wird erläutert, wie Sie mithilfe von ES6-Klassen Vue nachahmen, um einen Beispielcode für die bidirektionale Bindung zu schreiben und ihn mit allen zu teilen. Die Details sind wie folgt:
Der endgültige Effekt lautet wie folgt:
Konstruktor (Konstruktor)
Konstruiert ein TinyVue-Objekt, einschließlich grundlegender Elemente, Daten und Methoden
class TinyVue{ constructor({el, data, methods}){ this.$data = data this.$el = document.querySelector(el) this.$methods = methods // 初始化 this._compile() this._updater() this._watcher() } }
Compiler (kompilieren)
wird verwendet, um das Klickereignis @click des V-Modells und des an das Eingabefeld gebundenen Elements zu analysieren und abzulegen. Down-Box.
Erstellen Sie zunächst eine Funktion zum Laden des Ereignisses:
// 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) } }) }
Eingabefeldereignis laden
this._initEvents('input, textarea', 'v-model', (i, key) => { i.addEventListener('input', () => { Object.assign(this.$data, {[key]: i.value}) }) })
Auswahlfeldereignis laden
this._initEvents('select', 'v-model', (i, key) => { i.addEventListener('change', () => Object.assign(this.$data, {[key]: i.options[i.options.selectedIndex].value})) })
Klickereignis laden
Das Klickereignis entspricht dem Ereignis in Methoden
this._initEvents('*', '@click', (i, key) => { i.addEventListener('click', () => this.$methods[key].bind(this.$data)()) })
Updater anzeigen (Updater)
Auf die gleiche Weise, Erstellen Sie zunächst eine öffentliche Funktion, um die Ansichten in verschiedenen Elementen zu verarbeiten, einschließlich des Werts von input und textarea, des Auswahlwerts von 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) } }) }
Eingabefeldansicht aktualisieren
this._initView('input, textarea', 'v-model', (i, key, data) => { i.value = data })
Auswahlfeld aktualisieren Ansicht
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 aktualisieren
Die Implementierungsmethode hier ist etwas niedrig, ich denke nur an regelmäßige Ersetzung {{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]) }) } })
Watcher (Beobachter)
Aktualisieren Sie die Ansicht, nachdem sich die Daten geändert haben
<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>
Alle Codes von 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})) }) } }
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass es für alle beim Lernen hilfreich sein wird. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website!
Verwandte Empfehlungen:
Einführung in die Verpackung von Vue2.0-Multi-Tab-Switching-Komponenten
Über die Vue-Formulardemo V-Modell Probleme mit bidirektionaler Bindung
Das obige ist der detaillierte Inhalt vonVerwenden Sie ES6-Klassen, um Vue zu imitieren und ein Beispiel für eine bidirektionale Bindung zu schreiben. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!