在前端开发过程中,如果项目不大,或者有需要使用到双向数据场景的简单页面,完全不需要使用vuejs之类的第三方库。
下面分享一个简介的双向数据绑定js代码。代码只要30+行,直接复制到您项目中即可使用。
给需要双向绑定的元素设置 bind-data 属性,属性值为数据对象的属性名,即可将该元素与数据对象的相应属性进行绑定。
使用示例:
<input type="number" type="text" bind-data="text1" />
<p bind-data="text1">默认值</p>
<script>
....,
//使用js动态修改,对应字段会自动更新
data.text1= '123';//新值
....,
</script>
测试:
<p bind-data="text1">默认值</p>
<script>
let data = new Proxy(
{},
{
set(obj, key, value) {
obj[key] = value;
const dataElements = document.querySelectorAll(`[bind-data="${key}"]`);
const funcElements = document.querySelectorAll('[bind-fun]');
dataElements.forEach((element) => {
element instanceof HTMLInputElement ? (element.value = value) : (element.innerText = value);
});
if (funcElements.length > 0) {
funcElements.forEach((element) => {
const funcName = element.getAttribute('bind-fun');
if (typeof window[funcName] !== 'function') return;
const func = window[funcName].bind(obj);
const val = func() || '';
element instanceof HTMLInputElement ? (element.value = val) : (element.innerText = val);
});
}
return true;
},
get(obj, key) {
return obj[key];
},
}
);
document.addEventListener('input', function (event) {
if (!event.target.hasAttribute('bind-data')) return;
data[event.target.getAttribute('bind-data')] = event.target.value;
});
</script>
绑定数据进行回调:
使用示例:
<div>单价:<input type="number" type="text" bind-data="price" /></div>
<div>数量:<input type="number" type="text" bind-data="quantity" /></div>
<div>总价:<span bind-fun="totalPrice">0</span></div>
<script>
function totalPrice(){
//this指向数据对象
return this.price * this.quantity;
}
</script>
测试:
单价:
<div>数量:<input type="number" type="text" bind-data="quantity" /></div>
<div>总价:<span bind-fun="totalPrice">0</span></div>
<script>
let data = new Proxy(
{},{
set(obj, key, value) {
obj[key] = value;
const dataElements = document.querySelectorAll(`[bind-data="${key}"]`);
const funcElements = document.querySelectorAll('[bind-fun]');
dataElements.forEach((element) => {
element instanceof HTMLInputElement ? (element.value = value) : (element.innerText = value);
});
if (funcElements.length > 0) {
funcElements.forEach((element) => {
const funcName = element.getAttribute('bind-fun');
if (typeof window[funcName] !== 'function') return;
const func = window[funcName].bind(obj);
const val = func() || '';
element instanceof HTMLInputElement ? (element.value = val) : (element.innerText = val);
});
}
return true;
},
get(obj, key) {
return obj[key];
},
}
);
document.addEventListener('input', function (event) {
if (!event.target.hasAttribute('bind-data')) return;
data[event.target.getAttribute('bind-data')] = event.target.value;
});
function totalPrice(){
return this.price * this.quantity;
}
</script>
下面是实现双向绑定代码:
let data = new Proxy({}, {
set(obj, key, value) {
obj[key] = value;
const dataElements = document.querySelectorAll(`[bind-data="${key}"]`);
const funcElements = document.querySelectorAll("[bind-fun]");
dataElements.forEach((element) => {
element instanceof HTMLInputElement ? (element.value = value) : (element.innerText = value);
});
if (funcElements.length > 0) {
funcElements.forEach((element) => {
const funcName = element.getAttribute("bind-fun");
if (typeof window[funcName] !== "function") return;
const func = window[funcName].bind(obj);
const val = func() || "";
element instanceof HTMLInputElement ? (element.value = val) : (element.innerText = val);
});
}
return true;
},
get(obj, key) {
return obj[key];
},
});
document.addEventListener("input", function (event) {
if (!event.target.hasAttribute("bind-data")) return;
data[event.target.getAttribute("bind-data")] = event.target.value;
});