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

20 实现双向绑定v-model #22

Open
xwjie opened this issue Jan 22, 2018 · 0 comments
Open

20 实现双向绑定v-model #22

xwjie opened this issue Jan 22, 2018 · 0 comments

Comments

@xwjie
Copy link
Owner

xwjie commented Jan 22, 2018

其实就是把x-model指令生成的渲染函数改成下面这样生成的一样即可。

 <input :value="name" @input="if($event.target.composing)return;name=$event.target.value.trim()"/>

实现

修改ast2renderstr代码

/**
 * 解析指令
 * @param {*} node
 */
function getDirectiveStr(node: any) {
  let dirs = node.directives

  let str = '';

  if (dirs && dirs.length > 0) {
    str += 'directives:['

    // why not use for..in, see eslint `no-restricted-syntax`
    for (let i = 0; i < dirs.length; i++) {
      const dir = dirs[i]

      // 把x-model转换为
      // <input :value="name" @input="if($event.target.composing)return;name=$event.target.value.trim()"/>
      if (dir.name == 'x-model') {
        parseModel(node, dir)
        continue
      }
      else if (alreadyDeal(dir.name)) {
        continue
      }

      str += '{'
      for (let key in dir) {
        str += JSON.stringify(key) + ':'

        const val = dir[key]

        // 把value的值修改为表达式,render的时候就可以计算
        if (key == 'value') {
          // 如果有value(表达式)
          if (val) {
            str += `(${val}),`
          }
          // 没有表达式,直接赋值一个true即可。
          else {
            str += 'true,'
          }
        } else {
          str += JSON.stringify(val) + ','
        }
      }
      str += '},'
    }

    str += '],'
  }

  return str
}

function alreadyDeal(dirname: string): boolean {
  return dirname == 'x-if' || dirname == 'x-else'
}


// FIXME 这里只处理了Input,还有其他的类型
// 把x-model转换为
// <input :value="name" @input="if($event.target.composing)return;name=$event.target.value.trim()"/>
function parseModel(node: Object, dir: Object) {
  let attrs = node.attrsMap || (node.attrsMap = Object.create(null))
  attrs[':value'] = dir.value
  attrs['@input'] = `if($event.target.composing)return;${dir.value}=$event.target.value.trim()`
}
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