Как сделать DOM реактивным с помощью функции рендеринга в Vue?

#javascript #vuejs2 #jsx

Вопрос:

Поэтому, по сути, я просто хочу изменить тип ввода с text на password при нажатии кнопки, вот что я пытался:

Я попытался сделать экземпляр Vue наблюдаемым с Vue.observable помощью этого var и использовать его для изменения состояния, что, похоже, работает нормально, но когда я изменяю значение, кажется, что DOM не обновляется, результат, который я получаю, — это просто исчезающее значение ввода.

Как вы можете видеть в следующем MaskedInputElement методе, я устанавливаю атрибут типа ввода, с помощью data.type которого определяется моя переменная состояния Vue.observable .

MaskedInputPassword при нажатии кнопки я вызываю метод togglePassword , который просто задает значение переменной prop type состояния text , но DOM не обновляется, он продолжает отображаться type="password" .

Поэтому мой вопрос в том, как я могу заставить DOM реагировать на мои переменные? Возможно ли это?

 <script>
import MaskedInput from 'vue-text-mask'
import Vue from 'vue'

const data = Vue.observable({
  type: ''
})

const applyState = (props) => {
  for (const prop in props) {
    data[prop] = props[prop]
  }
}

const togglePassword = (e) => {
  e.preventDefault()
  data.type = 'text'
}

function MaskedInputElement (h, context) {
  return (
    <MaskedInput
      class="form-control"
      attrs={context.data.attrs}
      listeners={context.data.listeners}
      mask={context.props.mask}
      type={data.type}
    />
  )
}

function MaskedInputPassword (h, context) {
  return (
    <div class="input-group">
      { MaskedInputElement(h, context) }

      <div class="input-group-append">
        <button
          class="btn btn-outline-primary"
          onClick={e => togglePassword(e, context)}
        >
          <i class="fas fa-eye-slash fa-fw" />
        </button>
      </div>
    </div>
  )
}

export default {
  functional: true,
  props: {
    mask: {
      type: Boolean,
      default: false
    }
  },
  render: (h, context) => {
    applyState({
      type: context.data.attrs.type || 'text'
    })

    if (context.data?.attrs?.type === 'password') {
      return MaskedInputPassword(h, context)
    }

    return MaskedInputElement(h, context)
  }
}
</script>