zoukankan      html  css  js  c++  java
  • vue双向绑定笔记

    原文:https://github.com/louzhedong/blog/issues/4

    <!DOCTYPE html>
    <html lang="en">

    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    </head>

    <body>
    <div id="app">
    <form>
    <input type="text" v-model="number">
    <button type="button" v-click="increment">增加</button>
    </form>
    <h3 v-bind="number"></h3>
    </div>
    <script>
    function myVue(options) {
    this._init(options)
    }
    myVue.prototype._init = function (options) { // 参数 el: '#app',data: {number: 0},methods: {increment: function () {this.number++}}
    this.$options = options
    this.$el = document.querySelector(options.el) // 找到指定元素
    this.$data = options.data // data中的数据结构,如number:0
    this.$methods = options.methods // methods中的数据结构,如increment:function(){this.number++}
    this._binding = {}
    this._obverse(this.$data)
    this._complie(this.$el)
    }

    myVue.prototype._obverse = function (obj) { // data结构,如number:0
    var _this = this
    Object.keys(obj).forEach(function (key) { // Object.keys()返回对象的Key
    if (obj.hasOwnProperty(key)) { // 对象是否包含指定属性,返回boolean
    _this._binding[key] = {
    _directives: []
    }
    console.log(_this._binding[key])
    var value = obj[key]
    if (typeof value === 'object') { // 如果还是对象继续遍历
    _this._obverse(value)
    }
    var binding = _this._binding[key]
    // 定义属性描述 参数一定义属性的对象,参数二定义属性名称,参数三属性描述
    Object.defineProperty(_this.$data, key, {
    enumerable: true, // 开启才能出现在对象的枚举属性中
    configurable: true, // 开启属性描述才能改变,同时属性能删除
    get: function () { // 给属性提供getter方法
    console.log(`${key}获取${value}`)
    return value
    },
    set: function (newVal) { // 给属性提供setter方法
    console.log(`${key}更新${value}`)
    if (value !== newVal) {
    value = newVal
    binding._directives.forEach(function (item) {
    item.update()
    })
    }
    }
    })
    }
    })
    }
    myVue.prototype._complie = function (root) {
    var _this = this
    var nodes = root.children
    for (var i = 0; i < nodes.length; i++) {
    var node = nodes[i]
    if (node.children.length) {
    this._complie(node)
    }
    if (node.hasAttribute('v-click')) {
    node.onclick = (function () {
    var attrVal = nodes[i].getAttribute('v-click')
    return _this.$methods[attrVal].bind(_this.$data)
    })()
    }
    if (node.hasAttribute('v-model') && (node.tagName == 'INPUT' || node.tagName == 'TEXTAREA')) {
    node.addEventListener('input', (function (key) {
    var attrVal = node.getAttribute('v-model')
    _this._binding[attrVal]._directives.push(new Watcher(
    'input',
    node,
    _this,
    attrVal,
    'value'
    ))
    return function () {
    _this.$data[attrVal] = nodes[key].value
    }
    })(i))
    }
    if (node.hasAttribute('v-bind')) {
    var attrVal = node.getAttribute('v-bind')
    _this._binding[attrVal]._directives.push(new Watcher(
    'text',
    node,
    _this,
    attrVal,
    'innerHTML'
    ))
    }
    }
    }

    function Watcher(name, el, vm, exp, attr) {
    this.name = name // 指令名称,如文本节点text
    this.el = el // 指令对应DOM元素
    this.vm = vm // 指令所属myVue实例
    this.exp = exp // 指令对应值,如number
    this.attr = attr // 指令属性值,如innerHTML
    this.update()
    }
    Watcher.prototype.update = function () {
    this.el[this.attr] = this.vm.$data[this.exp] // 触发值改变,会调属性get方法
    }
    window.onload = function () { // 页面初始化创建实例
    var app = new myVue({
    el: '#app',
    data: {
    number: 0
    },
    methods: {
    increment: function () {
    this.number++
    }
    }
    })
    }
    </script>
    </body>

    </html>
  • 相关阅读:
    实现死锁
    mutex互斥锁
    共享内存实现进程间通信
    无名管道进程间通信
    文件拷贝
    linux 面试
    /etc/profile、/etc/bashrc、~/.bash_profile、~/.bashrc(转载)
    统计文件中制定词汇出现的次数
    指针之间的加减法
    CSS3权威指南-浮动3
  • 原文地址:https://www.cnblogs.com/victory820/p/8986077.html
Copyright © 2011-2022 走看看