[JS]原生使用Object.defineProperty劫持数据,实现响应式数据驱动DOM(借助VUE2.X的核心思想)

举个栗子

点击按钮只修改响应式数据,达到DOM更新和数据更新的功能
在这里插入图片描述

核心思想

定义一个即将被监听劫持的对象 => 给每一个对象.属性增加Object.defineProperty(),从而实现修改属性是会触发getter和setter

  • getter 用于获取被劫持后计算出指定的结果
  • setter 监听到修改操作时,由setter进行更新相关DOM
  • 定义需要被劫持的响应式对象数据
    在这里插入图片描述

  • 对于定义的数据进行针对劫持,使用getter和setter进行对DOM的处理
    在这里插入图片描述

  • 当点击功能按钮时,只需要修改定义的响应式数据就可以
    在这里插入图片描述

完整代码

供体验 希望大佬指点不足之处
供参考 下方注释掉的是JS原生操作DOM实现的

<html>
	<head>
		<title>操作DOM</title>
	</head>
	<style>
		.context,.footer{
			display: inline-block;
		}
	</style>
	<script>
		window.onload=function(){
			let data = {
				checkedLen:null,/**获取当前选中的数量*/
				count:null,/**获取当前所有的item数量*/
				checkboxAll:false,/**手动全选后勾选[全选/全不选]*/
				selectAll:false,/**控制点击[全选]按钮*/
				allDontChoose:true,/**控制点击[全不选]按钮*/
				inverse:false,/**控制点击[反选]按钮*/
			}
			let items=document.getElementsByName('checkbox')
			
			/**获取当前选中的数量*/
			Object.defineProperty(data,'checkedLen',{
				get:function(){
					let items=document.getElementsByName('checkbox')
					let len = 0
					for (const item of items) {
						if(item.checked) len++
					}
					return len
				},
			})
			/**获取当前所有的item数量*/
			Object.defineProperty(data,'count',{
				get:function(){
					let items=document.getElementsByName('checkbox')
					return items.length
				}
			})
			/**手动全选后勾选[全选/全不选]*/
			Object.defineProperty(data,'checkboxAll',{
				get:function(){
					return data.checkedLen == data.count
				},
				set:function(newValue){
					let all = document.getElementById('all')
					all.checked = newValue
					if((data.checkedLen == data.count) || newValue){
						for (let item of items) {
							item.checked = newValue
						}
					}
					
				},
			})
			/**控制点击[全选]按钮*/
			Object.defineProperty(data,'selectAll',{
				get:function(){
					return data.checkedLen == data.count
				},
				set:function(newValue){
					let selectAll = document.getElementById('selectAll');
					selectAll.disabled = newValue
					if(newValue){
						for (let item of items) {
							item.checked = newValue
						}
					}
				},
			})
			/**控制点击[全不选]按钮*/
			Object.defineProperty(data,'allDontChoose',{
				get:function(){
					return data.checkedLen == null || data.checkedLen === 0
				},
				set:function(newValue){
					let allDontChoose = document.querySelector('#allDontChoose')
					allDontChoose.disabled = newValue
					if(newValue){
						for (let item of items) {
							item.checked = !newValue
						}
					}
				}
			})
			/**控制点击[反选]按钮*/
			Object.defineProperty(data,'inverse',{
				set:function(newValue){
					for (let item of items) {
						item.checked = !item.checked
					}
				}
			})
			
			data.allDontChoose = true
			for (const item of items) {
				item.onclick = function(){
					data.selectAll = data.checkedLen == items.length
					data.checkboxAll = data.checkedLen == items.length
					data.allDontChoose = data.checkedLen == null || data.checkedLen === 0
				}
			}
			/**全选*/
			let selectAll = document.getElementById('selectAll')
			selectAll.addEventListener('click',function(){
				data.selectAll = true
				data.checkboxAll = true
				data.allDontChoose = false
			})
			/*全选/全不选*/
			let checkboxAll = document.getElementById('all')
			checkboxAll.addEventListener('click',function(){
				data.selectAll = this.checked
				data.checkboxAll = this.checked
				data.allDontChoose = !this.checked
			})
			/*全不选*/
			let allDontChoose = document.getElementById('allDontChoose')
			allDontChoose.addEventListener('click',function(){
				data.allDontChoose = true
				data.selectAll = false
				data.checkboxAll = false
			})
			/**反选*/
			let inverse = document.getElementById('inverse')
			inverse.addEventListener('click',function(){
				data.inverse = true
				if(data.checkedLen === 0 ){
					data.selectAll = false
					data.checkboxAll = false
					data.allDontChoose = true
				}else if(data.checkedLen < data.count){
					data.selectAll = false
					data.checkboxAll = false
				}else{
					data.selectAll = true
					data.checkboxAll = true
					data.allDontChoose = false
				}
			})
			let submit = document.getElementById('submit')
			submit.addEventListener('click',function(){
				let chooseMatter = []
				for (const item of items) {
					if(item.checked) chooseMatter = [...chooseMatter,item.value]
				}
				alert(!!chooseMatter.length ? chooseMatter:'没有选择,请勾选喜欢的球')
			})
		}
	</script>
	<body>
		<form style="max-width: 500px;">
			<h3>JS原生使用Object.defineProperty劫持数据,实现响应式数据驱动DOM(借助VUE2.0的核心思想)</h3>
			<fieldset>
				<legend><label><input type="checkbox" id="all"/> 全选 / 全不选</label></legend>
				<div class="context">
					<label><input type="checkbox" name="checkbox" value="0" /> 篮球</label>
					<label><input type="checkbox" name="checkbox" value="1" /> 足球</label>
					<label><input type="checkbox" name="checkbox" value="2" /> 排球</label>
					<label><input type="checkbox" name="checkbox" value="3" /> 冰球</label>
					<label><input type="checkbox" name="checkbox" value="4" /> 花球</label>
				</div>
				<div class="footer">
					<input type="button" value="全选" id="selectAll"></input>
					<input type="button" value="全不选" id="allDontChoose"></input>
					<input type="button" value="反选" id="inverse"></input>
					<input type="button" value="提交" id="submit"></input>
				</div>
			</fieldset>
		</form>
		<script>
			// window.onload = function(){
			// 	let all = document.getElementById('all') /**全选/全不选*/
			// 	let allCheckbox = document.getElementsByName('checkbox')
			// 	for (const item of allCheckbox) {
			// 		item.onclick = function(){
			// 			if(!all.checked) all.checked = true
			// 			for (const i of allCheckbox) {
			// 				if(!i.checked) all.checked = false
			// 			}
			// 		}
			// 	}
			// 	all.addEventListener('click',function(){
			// 		for (let item of allCheckbox) {
			// 			if(item.checked != this.checked) item.checked = this.checked
			// 		}
			// 	})
			// 	let selectAll = document.getElementById('selectAll')
			// 	selectAll.addEventListener('click',function(){
			// 		for (let item of allCheckbox) {
			// 			if(!item.checked) item.checked = true
			// 		}
			// 		all.checked = true
			// 	})
			// 	let allDontChoose = document.getElementById('allDontChoose')
			// 	allDontChoose.addEventListener('click',function(){
			// 		for (let item of allCheckbox) {
			// 			if(item.checked) item.checked = false
			// 		}
			// 		all.checked = false
			// 	})
			// 	let inverse = document.getElementById('inverse')
			// 	inverse.addEventListener('click',function(){
			// 		all.checked = true
			// 		for (let item of allCheckbox) {
			// 			item.checked = !item.checked
			// 			if(!item.checked) all.checked = false
			// 		}
			// 	})
			// 	let submit = document.getElementById('submit')
			// 	submit.addEventListener('click',function(){
			// 		let chooseMatter = []
			// 		for (const item of allCheckbox) {
			// 			if(item.checked) chooseMatter = [...chooseMatter,item.value]
			// 		}
			// 		console.log(chooseMatter)
			// 	})
			// }
		</script>
	</body>
</html>
微信扫一扫,免费保护车主号码隐私挪车码即可到手免费使用

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值