webfansplz / vuejs-challenges

Collection of Vue.js challenges
https://vuejs-challenges.netlify.app/
MIT License
2.72k stars 188 forks source link

26 - 实现简易版`v-model`指令 #1319

Open codelo-99 opened 1 year ago

codelo-99 commented 1 year ago
<script setup lang='ts'>

import { ref, defineExpose, toRef, watchEffect } from "vue"

/**
 * Implement a custom directive
 * Create a two-way binding on a form input element
 *
*/
const VOhModel = {
  mounted(el,binding,vnode,prevVnode){
    const arg = binding.arg
    const instanceModelRef = toRef(binding.instance, arg)
    el.$unwatch = watchEffect(()=>{
      el.value = instanceModelRef.value
    })
    el.$onInput = function(event){
      instanceModelRef.value = event.target.value
    }
    el.addEventListener('input',el.$onInput)
  },
  unmounted(el,binding,vnode,prevVnode){
    el.$unwatch()
    delete el.$unwatch
    el.removeEventListener('input',el.$onInput)
    delete el.$onInput
  }
}

const value = ref("Hello Vue.js")
const value2 = ref('1234')
defineExpose({
  value,
  value2,
})
</script>

<template>
  <p>
    <label>value:</label><input v-oh-model:value type="text" />{{ value }}
  </p>
  <p>
    <label>value:</label><input v-oh-model:value2 type="text" />{{ value2 }}
  </p>
</template>

Vue SFC Playground 在线链接

bLanK-NULL commented 8 months ago

与原装的v-model比起来,1. 在setup语法糖形式下要手动暴露变量; 2. 修改了原生语法 v-model=" " , 可惜的是不改成v-model:xxx 似乎就做不了了,因为拿不到绑定变量的引用只能拿到值,这一点实在是太啥比了