Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue教程06:数据同步、双向绑定原理 #7

Open
chencl1986 opened this issue Mar 18, 2019 · 0 comments
Open

Vue教程06:数据同步、双向绑定原理 #7

chencl1986 opened this issue Mar 18, 2019 · 0 comments

Comments

@chencl1986
Copy link
Owner

阅读更多系列文章请访问我的GitHub博客,示例代码请访问这里

利用Proxy实现数据同步

代码示例:/lesson06/01. 数据同步

利用Proxy拦截可以对数据的修改,得知数据被修改时,将模板中相应属性的部分替换,就完成了简单的数据同步功能。

const el = document.querySelector('#app')

// 获取标签内容作为页面模板
let template = el.innerHTML

// _data为初始化
let _data = {
  name: 'lee',
  age: 18
}

// 为_data设置拦截,通过修改data中属性的值,来修改
let data = new Proxy(_data, {
  // 当数据修改时,会被set方法拦截,从而得知数据被修改的值value,之后可以将value渲染到页面中,obj为_data
  set(obj, key, value) {
    console.log(`设置${key}属性为${value}`)
    obj[key] = value

    // 将数据渲染到页面中
    render()
  }
})

// 初始化时渲染页面
render()

function render() {
  // 将模板中{{}}内部的内容,用数据替换
  el.innerHTML = template.replace(/\{\{\w+\}\}/g, str => {
    str = str.substring(2, str.length - 2);

    return _data[str];
  })
}

HTML:

<div id="app">
  姓名:{{name}}<br/>
  年龄:{{age}}
</div>

数据双向绑定

在data改变时,查找页面中含有相应v-model属性的input标签,将input的value值改为data的值。
同时在input标签的值变化时,将input的值设置为data的值,就实现了双向绑定。

JavaScript:

const el = document.querySelector('#app')

// 获取标签内容作为页面模板
let template = el.innerHTML

// _data为初始化
let _data = {
  name: 'lee',
  age: 18
}

// 为_data设置拦截,通过修改data中属性的值,来修改
let data = new Proxy(_data, {
  // 当数据修改时,会被set方法拦截,从而得知数据被修改的值value,之后可以将value渲染到页面中,obj为_data
  set(obj, key, value) {
    console.log(`设置${key}属性为${value}`)
    obj[key] = value

    // 将数据渲染到页面中
    render()
  }
})

// 初始化时渲染页面
render()

function render() {
  // 将模板中{{}}内部的内容,用数据替换
  el.innerHTML = template.replace(/\{\{\w+\}\}/g, str => {
    str = str.substring(2, str.length - 2);

    return _data[str];
  })

  // 但检测到数据改变时,将input的值同步
  Array.from(document.getElementsByTagName('input'))
    // 查找含有v-model属性,即设置了双向绑定的input
    .filter((ele) => ele.getAttribute('v-model'))
    .forEach((input, index) => {
      const name = input.getAttribute('v-model')
      input.value = _data.name

      // 输入框的值变化时,将data中相应属性的值改变
      input.oninput = function () {
        data[name] = input.value
      }
    })
}

HTML:

<div id="app">
  <input type="text" v-model="name"><br />
  姓名:{{name}}<br/>
  年龄:{{age}}
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant