大部分人在看到这篇文章的标题时第一时间可能有点懵,我先简单介绍一下背景:
公司有一个基于Vue实现的登录中心是我负责维护的,页面上是一个常规的登录界面,用户名输入框、密码输入框和登录按钮各一个
今天有个同事(之后简称A)过来找我问到这么一个问题:
他负责的应用将登录中心集成到了APP端,他接到的需求是希望在APP端拉起登录页面时,自动将用户帐号和密码填入,然后自动点击登录。
我们把登录页面简化成以下代码
<span class="hljs-tag"><<span class="hljs-name">template>
<span class="hljs-tag"><<span class="hljs-name">div>
<span class="hljs-tag"><<span class="hljs-name">input <span class="hljs-attr">name=<span class="hljs-string">"username" <span class="hljs-attr">type=<span class="hljs-string">"text" <span class="hljs-attr">v-model=<span class="hljs-string">"account.username">
<span class="hljs-tag"><<span class="hljs-name">input <span class="hljs-attr">name=<span class="hljs-string">"password" <span class="hljs-attr">type=<span class="hljs-string">"password" <span class="hljs-attr">v-model=<span class="hljs-string">"account.password">
<span class="hljs-tag"><<span class="hljs-name">button <span class="hljs-attr">class=<span class="hljs-string">"login-button" @<span class="hljs-attr">click=<span class="hljs-string">"login">LOGIN<span class="hljs-tag">button>
<span class="hljs-tag">div>
<span class="hljs-tag">template>
<span class="hljs-tag"><<span class="hljs-name">script><span class="javascript">
<span class="hljs-keyword">export <span class="hljs-keyword">default {
<span class="hljs-attr">name: <span class="hljs-string">'app',
<span class="hljs-attr">components: {
},
data () {
<span class="hljs-keyword">return {
<span class="hljs-attr">account: {
<span class="hljs-attr">username: <span class="hljs-string">'',
<span class="hljs-attr">password: <span class="hljs-string">''
}
}
},
<span class="hljs-attr">methods: {
login () {
$ajax({
<span class="hljs-attr">method: <span class="hljs-string">'POST',
<span class="hljs-attr">url: <span class="hljs-string">'/api/login',
<span class="hljs-attr">data: <span class="hljs-keyword">this.account
})
}
}
}
<span class="hljs-tag">script>
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
APP端在拉起登录页面时,可以传入js代码并在当前页面执行,抛开MVVM框架Vue的影响,在前端的远古时代这其实是个很简单的问题
<span class="hljs-keyword">const usernameInput = <span class="hljs-built_in">document.querySelector(<span class="hljs-string">'input[name=username]')
<span class="hljs-keyword">const passwordInput = <span class="hljs-built_in">document.querySelector(<span class="hljs-string">'input[name=password]')
<span class="hljs-keyword">const button = <span class="hljs-built_in">document.querySelector(<span class="hljs-string">'.login-button')
usernameInput.value = <span class="hljs-string">'test@dji.com' </span></span></span></span></span></span></span></span></span></span>
上面也正是同事A所尝试的方法,然而他在实际测试中发现,运行js后,虽然页面上的input框正确变更为修改后的值,但发起的ajax请求中 username
和 password
均为空字符串,于是将问题反馈到了我这边
其实如果对Vue的响应式数据原理有一定理解的话,就可以很快的想到这个问题的原因。问题的根源就在 v-model 的原理上:
v-model
其实是vue为了方便使用提供的一个语法糖,实际展开来是这样子
<input name="<span" class="hljs-string">"username" <span class="hljs-built_in">type=<span class="hljs-string">"text" :value=<span class="hljs-string">"account.username" @input=<span class="hljs-string">"account.username = <span class="hljs-variable">$event.target.value">
</span></span></span></span></span>
当用户在输入框输入时会触发input事件,从而更新 account.username
值
而上一步中使用
<span class="hljs-built_in">document.querySelector(<span class="hljs-string">'input[name=username]').value = <span class="hljs-string">'test@dji.com'
</span></span></span>
模拟的输入行为实际上并不能触发 oninput
事件,那么模拟 button 的点击事件后发起的 ajax 请求拿到的数据自然也就是未修改前的值(即空字符串)
弄明白了问题的原理之后,解决方案自然也就很容易想到。既然js模拟输入无法触发 oninput
事件,那我们就再进一步,在修改完值后用js手动触发 oninput
事件
实现代码如下:
<span class="hljs-keyword">const usernameInput = <span class="hljs-built_in">document.querySelector(<span class="hljs-string">'input[name=username]')
<span class="hljs-keyword">const passwordInput = <span class="hljs-built_in">document.querySelector(<span class="hljs-string">'input[name=password]')
<span class="hljs-keyword">const button = <span class="hljs-built_in">document.querySelector(<span class="hljs-string">'.login-button')
<span class="hljs-keyword">const event = <span class="hljs-built_in">document.createEvent(<span class="hljs-string">'HTMLEvents')
event.initEvent(<span class="hljs-string">'input', <span class="hljs-literal">false, <span class="hljs-literal">true)
usernameInput.value = <span class="hljs-string">'test@dji.com' </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
以上代码未考虑兼容性、代码封装等问题,仅提供解决思路的参考
其实问题说不上多难,但是对于很多学习知识时只是浅尝辄止的同学,很可能会是个不小的麻烦。平时经常能听到一些 框架会用就行了,原理什么的也就应付一下面试,工作压根用不到
之类的言论,希望大家可以在日趋浮躁的大环境下,守住极客精神,认真钻研技术,做一个真正的程序员,而不仅仅只是个搬砖的。
Original: https://www.cnblogs.com/waw/p/15531898.html
Author: 狼人:-)
Title: JS响应式修改基于vue实现的页面的input值
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/546216/
转载文章受原作者版权保护。转载请注明原作者出处!