• JS响应式修改基于vue实现的页面的input值 狼人:


    大部分人在看到这篇文章的标题时第一时间可能有点懵,我先简单介绍一下背景:

    公司有一个基于Vue实现的登录中心是我负责维护的,页面上是一个常规的登录界面,用户名输入框、密码输入框和登录按钮各一个

    今天有个同事(之后简称A)过来找我问到这么一个问题:

    他负责的应用将登录中心集成到了APP端,他接到的需求是希望在APP端拉起登录页面时,自动将用户帐号和密码填入,然后自动点击登录。

    开始正题

    我们把登录页面简化成以下代码

    <template>
      <div>
        <input name="username" type="text" v-model="account.username">
        <input name="password" type="password" v-model="account.password">
        <button class="login-button" @click="login">LOGIN</button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'app',
      components: {
      },
      data () {
        return {
          account: {
            username: '',
            password: ''
          }
        }
      },
      methods: {
        login () {
          $ajax({
            method: 'POST',
            url: '/api/login',
            data: this.account
          })
        }
      }
    }
    </script>
    

    APP端在拉起登录页面时,可以传入js代码并在当前页面执行,抛开MVVM框架Vue的影响,在前端的远古时代这其实是个很简单的问题

    const usernameInput = document.querySelector('input[name=username]')
    const passwordInput = document.querySelector('input[name=password]')
    const button = document.querySelector('.login-button')
    
    usernameInput.value = 'test@dji.com' // 修改用户名输入框的值
    passwordInput.value = 'xxxxxxxx' // 修改密码输入框的值
    
    button.click() // 触发按钮点击事件
    

    上面也正是同事A所尝试的方法,然而他在实际测试中发现,运行js后,虽然页面上的input框正确变更为修改后的值,但发起的ajax请求中 username 和 password 均为空字符串,于是将问题反馈到了我这边

    原理

    其实如果对Vue的响应式数据原理有一定理解的话,就可以很快的想到这个问题的原因。问题的根源就在 v-model 的原理上:

    v-model 其实是vue为了方便使用提供的一个语法糖,实际展开来是这样子

    <input name="username" type="text" :value="account.username" @input="account.username = $event.target.value">
    

    当用户在输入框输入时会触发input事件,从而更新 account.username 值

    而上一步中使用

    document.querySelector('input[name=username]').value = 'test@dji.com'
    

    模拟的输入行为实际上并不能触发 oninput 事件,那么模拟 button 的点击事件后发起的 ajax 请求拿到的数据自然也就是未修改前的值(即空字符串)

    解决方案

    弄明白了问题的原理之后,解决方案自然也就很容易想到。既然js模拟输入无法触发 oninput 事件,那我们就再进一步,在修改完值后用js手动触发 oninput 事件

    实现代码如下:

    const usernameInput = document.querySelector('input[name=username]')
    const passwordInput = document.querySelector('input[name=password]')
    const button = document.querySelector('.login-button')
    
    const event = document.createEvent('HTMLEvents')
    event.initEvent('input', false, true)
    
    usernameInput.value = 'test@dji.com' // 修改用户名输入框的值
    usernameInput.dispatchEvent(event) // 手动触发输入框的input事件
    
    passwordInput.value = 'xxxxxxxx' // 修改密码输入框的值
    passwordInput.dispatchEvent(event) // 手动触发输入框的input事件
    
    button.click() // 触发按钮点击事件
    

    以上代码未考虑兼容性、代码封装等问题,仅提供解决思路的参考

    写在最后

    其实问题说不上多难,但是对于很多学习知识时只是浅尝辄止的同学,很可能会是个不小的麻烦。平时经常能听到一些 框架会用就行了,原理什么的也就应付一下面试,工作压根用不到 之类的言论,希望大家可以在日趋浮躁的大环境下,守住极客精神,认真钻研技术,做一个真正的程序员,而不仅仅只是个搬砖的。

    声明:此博有部分内容为转载,版权归原作者所有~
  • 相关阅读:
    PTA 1022 Digital Library (30分) 坑多需谨慎!!!
    PAT 1013 Battle Over Cities (25分) 图的连通分量+DFS
    PAT 1021 Deepest Root (25分) 从测试点3超时到满分再到代码优化
    Java面向对象-------多态总结
    C后端设计开发
    C后端设计开发
    C后端设计开发
    C后端设计开发
    C后端设计开发
    一个真正的客户端非阻塞的 connect
  • 原文地址:https://www.cnblogs.com/waw/p/15531898.html
Copyright © 2020-2023  润新知