vue技术

目录

理解MVVM

MVVM模型

MVVM简介

MVVM模型

vue.js中MVVM的体现

Vue.js关于双向数据绑定的一些实现细节

 _Object.defineProperty

语法

参数

实例

 数据和视图联动

理解数据代理

代码实现

 第二个例子:person1中的age跟person2中一致

vue中的数据代理

 事件处理

监听事件

示例

事件处理方法

事件修饰符

新增

新增

键盘事件

属性

键盘相应顺序

事件总结

资源事件

网络事件


理解MVVM

MVVM模型

MVVM简介

MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自动传递给 View,即所谓的数据双向绑定。
  Vue.js 是一个提供了 MVVM 风格的双向数据绑定的 Javascript 库,专注于View 层。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel负责连接 View 和 Model,保证视图和数据的一致性,这种轻量级的架构让前端开发更加高效、便捷。


MVVM模型

MVVM模型图示

 MVVM拆开来即为Model-View-ViewModel,有View,ViewModel,Model三部分组成。View层代表的是视图、模版,负责将数据模型转化为UI展现出来。Model层代表的是模型、数据,可以在Model层中定义数据修改和操作的业务逻辑。ViewModel层连接Model和View。
  在MVVM的架构下,View层和Model层并没有直接联系,而是通过ViewModel层进行交互。ViewModel层通过双向数据绑定将View层和Model层连接了起来,使得View层和Model层的同步工作完全是自动的。因此开发者只需关注业务逻辑,无需手动操作DOM,复杂的数据状态维护交给MVVM统一来管理。


vue.js中MVVM的体现

Vue.js的实现方式,对数据(Model)进行劫持,当数据变动时,数据会出发劫持时绑定的方法,对视图进行更新。

vue中MVVM的体现

Vue.js关于双向数据绑定的一些实现细节

下面我又简单的了解了一下Vue.js关于双向数据绑定的一些实现细节;主要参考了下面这篇文章,很有研究价值,有意向者可以去看一下:
深入MVVM模型带你理解Vue.js的双向绑定

  vue是采用Object.defineProperty的getter和setter,并结合观察者模式来实现数据绑定的。当把一个普通的javascript对象传给Vue实例来作为它的data选项时,Vue将遍历它的属性,用Object.defineProperty将它们转为getter/setter。用户看不到getter/setter,但是在内部它们让Vue追踪依赖。在属性被访问和修改时通知变化。


Observer数据监听器,能够对数据对象的所有属性进行监听,如有变动可拿到最新的值并通知订阅者,内部采用的Obiect.defineProperty的getter和setter来实现。
complie指令解析器,它的作用对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定Observer和Complie的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应的回调函数
Watcher订阅者,作为连接Observer和Complie的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数。
Dep消息订阅器,内部维护了一个数组,用来收集订阅者(watcher),数据变动触发notify函数,再调用订阅者的update方法。
 

 _Object.defineProperty

Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。

语法

Object.defineProperty(obj, prop, descriptor)

参数

  • obj 需要定义属性的对象。
  • prop 需被定义或修改的属性名。
  • descripter 需被定义或修改的属性的描述符。

实例

var o={};//创建一个新对象
Object.defineProperty(o,"a",{
    //该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined
    value:37,
    // 仅当仅当该属性的writable为 true 时,该属性才能被赋值运算符改变。默认为 false
    writable:true,
    //仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false
    enumerable:true,
    // 仅当该属性的 configurable 为 true 时,该属性才能够被改变,也能够被删除。默认为 false
    configurable:true
});
// 对象o拥有了属性a,值为37

var bValue;
Object.defineProperty(o,"b",{
    get:function () { return bValue; },
    set:function (v) { bValue=v; },
    enumerable:true,
    configurable:true
});
o.b=45;

 数据和视图联动

给对象o定义新的属性b,并且定义属性b的get和set方法,当o.b的时候会调用b属性的get方法,给b属性赋值的时候,会调用set方法,这就是修改数据的时候,视图会自动更新的关键
前端获取数据后,需要根据数据操作dom,视图变化后,需要修改不少代码,有没有方法将数据和dom操作隔离,看一个例子,显示用户信息的html模版。

<div>
    <p>你好,<span id='nickName'></span></p>
    <div id="introduce"></div>
</div>  
//视图控制器
var userInfo = {};
Object.defineProperty(userInfo, "nickName", {
    get: function(){
        return document.getElementById('nickName').innerHTML;
    },
    set: function(nick){
        document.getElementById('nickName').innerHTML = nick;
    }
});
Object.defineProperty(userInfo, "introduce", {
    get: function(){
        return document.getElementById('introduce').innerHTML;
    },
    set: function(introduce){
        document.getElementById('introduce').innerHTML = introduce;
    }
});
//数据
//todo 获取用户信息的代码
//....

userInfo.nickName = "xxx";
userInfo.introduce = "我是xxx,我来自云南,..."

理解数据代理

在这里插入图片描述

代码实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./js/vue.js"></script>
</head>
<body>
    <div id='root'>
        <!-- <h1>hello {{name}} {{$mount}}</h1> -->
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false
        let num = 20
        let person = {
            name:'钢弹',sex:'males'
        }
        Object.defineProperty(
            person,
            'age',
            {
                // value:18,
                // enumerable:true,  // 支持枚举,枚举就是可遍历啥的,不然新增属性,遍历不出来!
                // writable:true,    // 控制属性是否能被 修改
                // configurable:true,// 控制属性是否能删除
                get(){
                  console.log('有人访问了person就会触发这个方法,从而让  = num')
                  return num;  
                },
                set(value){
                	console.log('有人修改person中的age的值,从而把num等于这个值')
                    num = value
                }
            }
        )
        console.log(person)
    </script>
</body>
</html>

 第二个例子:person1中的age跟person2中一致

let person1 = {
            name:'zhangsan'
        } 
        let person2 = {
            name:'lisi',age:4
        }
        Object.defineProperty(person1,'age',{
            get(){
                return person2.age
            },
            set(value){
                person2.age = value
            }
        })

vue中的数据代理

<script type="text/javascript">
            let num = 16
            let person = {
                name:"张三",
                //age:18,
                sex:'男'
            }
            Object.defineProperty(person,'age',{
                /*value:16,
                enumerable:true,//控制属性是否能被遍历
                writable:true,//控制属性是否可以被修改
                configurable:true,//控制属性是否可以被删除*/
                //有人读取age属性时,get函数(getter)就会被调用。且返回值就是return的值
                get(){
                    console.log('读取值了')
                    return num
                },
                //有人修改age属性时,set函数(setter)就会被调用。且返回值就是return的值
                set(val){
                    console.log('修改值了,且值为',val)
                    num = val;
                }
            })
            console.log(person)
1.Vue中的数据代理
     通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的 好处
      更加方便的操作data中的数据
3.基本原理:
     通过object.defineProperty()把data对象中的所有属性添加到vm上
     为每一个添加到vm上的属性,都指定一个getter和setter
     在getter/setter内部去操作data中对应的属性

 事件处理

监听事件

可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。

示例

<div id="example-1">
  <button v-on:click="counter += 1">Add 1</button>
  <p>The button above has been clicked {{ counter }} times.</p>
</div>
var example1 = new Vue({
  el: '#example-1',
  data: {
    counter: 0
  }
})

事件处理方法

然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on 指令中是不可行的。因此 v-on 还可以接收一个需要调用的方法名称。

<div id="example-2">
  <!-- `greet` 是在下面定义的方法名 -->
  <button v-on:click="greet">Greet</button>
</div>
var example2 = new Vue({
  el: '#example-2',
  data: {
    name: 'Vue.js'
  },
  // 在 `methods` 对象中定义方法
  methods: {
    greet: function (event) {
      // `this` 在方法里指向当前 Vue 实例
      alert('Hello ' + this.name + '!')
      // `event` 是原生 DOM 事件
      if (event) {
        alert(event.target.tagName)
      }
    }
  }
})

// 也可以用 JavaScript 直接调用方法
example2.greet() // => 'Hello Vue.js!'

事件修饰符

在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

新增

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

不像其它只能对原生的 DOM 事件起作用的修饰符,.once 修饰符还能被用到自定义的组件事件上。如果你还没有阅读关于组件的文档,现在大可不必担心。

新增

Vue 还对应 addEventListener 中的 passive 选项提供了 .passive 修饰符

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

这个 .passive 修饰符尤其能够提升移动端的性能。

不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你想阻止事件的默认行为

键盘事件

在 JavaScript 中,当用户操作键盘时,会触发键盘事件,键盘事件主要包括下面 3 种类型:

  • keydown:在键盘上按下某个键时触发。如果按住某个键,会不断触发该事件,但是 Opera 浏览器不支持这种连续操作。该事件处理函数返回 false 时,会取消默认的动作(如输入的键盘字符,在 IE 和 Safari 浏览器下还会禁止keypress 事件响应)。
  • keypress:按下某个键盘键并释放时触发。如果按住某个键,会不断触发该事件。该事件处理函数返回 false 时,会取消默认的动作(如输入的键盘字符)。
  • keyup:释放某个键盘键时触发。该事件仅在松开键盘时触发一次,不是一个持续的响应状态。


当获取用户正按下键码时,可以使用 keydown、keypress 和 keyup 事件获取这些信息。其中 keydown 和 keypress 事件基本上是同义事件,它们的表现也完全一致,不过一些浏览器不允许使用 keypress 事件获取按键信息。所有元素都支持键盘事件,但键盘事件多被应用在表单输入中。

<textarea id="key"></textarea>
<script>
    var key = document.getElementById("key");
    key.onkeydown =f;  //注册keydown事件处理函数
    key.onkeyup = f;  //注册keyup事件处理函数
    key.onkeypress = f;  //注册keypress事件处理函数
    function f (e) {
        var e = e || window.event;  //标准化事件处理
        var s = e.type + " " + e.keyCode;  //获取键盘事件类型和按下的值
        key.value = s;
    }
</script>

属性

键盘定义了很多属性,如下表所示。利用这些属性可以精确控制键盘操作。键盘事件属性一般只在键盘相关事件发生时才会存在于事件对象中,但是 ctrlKey 和 shiftKey 属性除外,因为它们可以在水保事件中存在。例如,当按下 Ctrl 或Shift 键时单击鼠标操作。

键盘事件定义的属性
属性说明
keyCode该属性包含键盘中对应键位的键值
charCode该属性包含键盘中对应键位的 Unicode 编码,仅 DOM 支持
target发生事件的节点(包含元素),仅 DOM 支持
srcElement发生事件的元素,仅 IE 支持
shiftKey是否按下 Shift 键,如果按下返回 true,否则为false
ctrlKey是否按下 Ctrl 键,如果按下返回 true,否则为false
altKey是否按下 Alt 键,如果按下返回 true,否则为false
metaKey

是否按下 Mtea 键,如果按下返回 true,否则为false,仅 DOM 支持

键盘相应顺序

 

当按下键盘时,会连续触发多个事件,它们将按如下顺序发生。

对于字符键来说,键盘事件的响应顺序:keydown → keypress → keyup。

对于非字符键(如功能键或特殊键)来说,键盘事件的相应顺序:keydown → keyup。

如果按下字符键不放,则 keydown 和 keypress 事件将逐个持续发生,直至松开按键。

如果按下非字符键不放,则只有 keydown 事件持续发生,直至松开按键。

事件总结

资源事件

事件名称何时触发
error资源加载失败时。
abort正在加载资源已经被中止时。
load资源及其相关资源已完成加载。
beforeunloadwindow,document 及其资源即将被卸载。
unload文档或一个依赖资源正在被卸载。

网络事件

事件名称何时触发
online浏览器已获得网络访问。
offline

浏览器已失去网络访问。

 

焦点事件

事件名称何时触发
focus元素获得焦点(不会冒泡)。
blur元素失去焦点(不会冒泡)。

WebSocket 事件

事件名称何时触发
openWebSocket 连接已建立。
message通过 WebSocket 接收到一条消息。
errorWebSocket 连接异常被关闭(比如有些数据无法发送)。
closeWebSocket 连接已关闭。

会话历史事件

事件名称何时触发
pagehideA session history entry is being traversed from.
pageshowA session history entry is being traversed to.
popstateA session history entry is being navigated to (in certain cases).

CSS 动画事件

事件名称何时触发
animationstart某个 CSS 动画开始时触发。
animationend某个 CSS 动画完成时触发。
animationiteration某个 CSS 动画完成后重新开始时触发。

CSS 过渡事件

事件名称何时触发
transitionstartCSS transition has actually started (fired after any delay).
transitioncancelCSS transition has been cancelled.
transitionendCSS transition has completed.
transitionrunCSS transition has begun running (fired before any delay starts).

表单事件

事件名称何时触发
reset点击重置按钮时
submit点击提交按钮

打印事件

时间名称何时触发
beforeprint打印机已经就绪时触发
afterprint打印机关闭时触发
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值