Vue2---(响应式数据,双向数据绑定,过滤器)

48 阅读1分钟

响应式数据

响应式数据:如果内存中的数据变化了 页面UI也会动态跟着刷新 这种数据就是响应式数据

响应式数据设计原理:

vue2.0 采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

vue3.0 --使用es6 proxy 代理了data对象

响应式数据实现原理:

<div id="app">
		<!-- <h1 v-html="title">{{msg}}</h1> -->
		<h1 v-html="title"></h1>
		<p>{{msg}}</p>
		<button @click="fn">change1</button>
	</div>
	<script>
		var vm = new Vue({
			el: "#app",
			data: {
				title: "hello",
				msg: "666"
			},
			methods: {
				fn() {
					for (let i = 0; i < 10000; i++) {
						this.title = i
					}
				}
			}
		})
	</script>

	<div id="myapp">
		<h1 id="title"></h1>
		<p id="msg"></p>
	</div>
	<script>
		function MyVue(option) {
			let _myvm = {}
			//劫持
			let arr = Object.keys(option.data) //["title","msg"]
			// _myvm[arr[0]]=option.data[arr[0]]
			// _myvm[arr[1]]=option.data[arr[1]]
			for (let i = 0; i < arr.length; i++) {
				Object.defineProperty(_myvm, arr[i], {
					set(v) {
						//劫持

						option.data[arr[i]] = v
						//响应-刷新页面
						let title = document.querySelector(option.el + " #title")
						let msg = document.querySelector(option.el + " #msg")
						title.innerHTML = _myvm["title"]
						msg.innerHTML = _myvm["msg"]
					},
					get() {
						return option.data[arr[i]]
					}
				})
				_myvm[arr[i]] = option.data[arr[i]]

			}


			return _myvm
		}

		var myvm = new MyVue({
			el: "#myapp",
			data: {
				title: "mytitle66666",
				msg: "mymsg666666",
				obj: {
					age: 10,
					name: "karen"
				},
				arr: [10, 230, 5]
			}
		})

双向数据绑定

双向数据绑定:代码改变UI,UI也能改变代码

双向数据绑定的实现: 2种方式

1.自己实现,vue可以自己实现(没必要) 微信开发可以自己实现(只能自己实现) 利用input事件,用户交互的时候,获取用户输入的值,然后把值绑定到data容器中

2.系统指令:v-model

vue实现数据双向绑定的原理:

采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

vue数据双向绑定实现:

//利用 Object.defineProperty 自己实现双向数据绑定
<body>
    <div id="app">
      <input type="text" id="txt">
      <p id="show"></p>
    </div>
</body>
<script type="text/javascript">
    var obj = {}
    Object.defineProperty(obj, 'txt', {
        get: function () {
            return obj[txt]
        },
        set: function (newValue) {
            document.getElementById('txt').value = newValue
            document.getElementById('show').innerHTML = newValue
        }
    })
    document.addEventListener('keyup', function (e) {
        obj.txt = e.target.value
    })
</script>

过滤器

filter主要用于数据展示之前的处理 过滤器只能用在v-bind或者插值表达式中

<div id="app">
			<p>{{a}}</p>
			<p>{{timerformatter(birth)}}</p>
			<p>{{birth|tool|tool2}}</p>
			<p>{{birth|tool3(100,200)}}</p>
			<a :href="url|tool4">baidu</a>
			<!-- <p v-text="birth|tool3"></p> -->
			<button @click="change1">change1</button>
		</div>
		<script>
			var vm=new Vue({
				el:"#app",
				data:{
					a:"测试",
					birth:"2007-02-03",
					url:"www.baidu.com"
				},
				methods:{
					change1(){
						this.a="66666"
					},
					timerformatter(str){
						console.log("调用了函数timerformatter--methods")
						let age=new Date().getFullYear()-new Date(str).getFullYear()
						return age+"岁"
					}
				},
				filters:{
					tool(str){
						console.log("调用了函数tool--filters")
						let age=new Date().getFullYear()-new Date(str).getFullYear()
						return age+"岁"
					},
					tool2(str){
						if(parseInt(str)>18){
							return "可以喝酒:"+str
						}else{
							return "禁止进入:"+str
						}
						 
					},
					tool3(arg1,arg2,arg3){
						console.log(arg1,arg2,arg3)
						return "hello"
					},
					tool4(url){
						return "http://"+url
					}
				}
			})
						
		</script>

image.png