이 글은 주로 ES6 클래스를 사용하여 Vue를 모방하여 양방향 바인딩 샘플 코드를 작성하는 방법을 소개합니다. 내용이 꽤 좋아서 지금 공유하고 참고하겠습니다.
이 기사에서는 Vue를 모방하여 양방향 바인딩 샘플 코드를 작성하고 모든 사람과 공유하기 위해 ES6 클래스를 사용하는 방법을 소개합니다.
최종 효과는 다음과 같습니다.
생성자(constructor)
Construction 기본 엘, 데이터, 메소드
class TinyVue{ constructor({el, data, methods}){ this.$data = data this.$el = document.querySelector(el) this.$methods = methods // 初始化 this._compile() this._updater() this._watcher() } }
Compiler(컴파일)
을 포함하는 TinyVue 객체는 입력 상자 및 드롭다운 상자에 바인딩된 v-모델을 구문 분석하는 데 사용됩니다. 그리고 요소의 클릭 이벤트 @click.
먼저 이벤트를 로드하는 함수를 만듭니다.
// 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) } }) }
입력 상자 이벤트 로드
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})) })
클릭 이벤트 로드
클릭 이벤트는 메서드의 이벤트에 해당합니다
this._initEvents('*', '@click', (i, key) => { i.addEventListener('click', () => this.$methods[key].bind(this.$data)()) })
업데이트 보기( 업데이트 프로그램)
마찬가지로 먼저 입력, 텍스트 영역 값, 값 선택, p의 innerHTML을 포함한 다양한 요소의 보기를 처리하는 공개 함수를 만듭니다.HTML
_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) } }) }
입력 상자 보기 업데이트
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') }) })
Update innerHTML
여기서 구현 방법은 약간 낮습니다. 정기적인 교체만 생각합니다. {{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]) }) } })
listener(watcher)
데이터 변경 후 뷰 업데이트
<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 codes
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 중국어 홈페이지를 주목해주세요!
관련 추천 :
Vue form 데모 v-model 양방향 바인딩 문제에 대하여
위 내용은 ES6 클래스를 사용하여 Vue를 모방하여 양방향 바인딩 예제 작성의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!