IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue响应式原理 -> 正文阅读

[JavaScript知识库]Vue响应式原理

一.深入响应式原理

Vue最独特的特性之一,是其非侵入性的响应式系统。数据模型仅仅是普通的JavaScrpit对象。而当你修改他们时,视图会进行更新。这使得状态管理非常简单直接,不过理解其工作原理同样重要,这样你可以避免一些常见的问题。接下来我们一起探究下吧。

二.Object.defineProperty属性

当你把普通的JavaScrpit对象传入Vue实例作为data选项,Vue将遍历此对象所有的property,并且使用Object.defineProperty?把这些property全部转为getter/setter。Object.defineProperty是ES5中一个无法shim的特性,这也就是Vue不支持IE8以及更低版本浏览器的原因。

关于对shim的解释

Vue响应式原理中:Object.defineProperty是Es5中无法shim的特性,那么这里的shim是什么呢?
定义:shim可以将新的API引入到旧的环境中,而且仅靠就环境中已有的手段实现。

这些getter/setter对用户来说是不可见的,但是在内部他们让Vue能够追踪依赖,在property被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对getter/setter的格式化并不同,所以建议安装vue-devtools来获取对检查数据更加友好的用户界面。

每个组件实例都对应watcher实例,它会在组件渲染的过程中把'接触'过的数据,property记录为依赖。之后当依赖项的setter触发时,会通知watcher,从而使它关联的组件重新渲染。?

图示:

三.检测变化的注意事项

(1)Vue不能检测数组和对象的变化

由于JavaScrpit的限制,Vue不能检测数组和对象的变化。尽管如此我们还是有一些办法来回避这些限制并保证它们的响应式。

(2)对于对象

Vue无法检测property的添加或移除。由于Vue会在初始化实例时对property执行getter/setter转化,所以property必须在data对象上存在才能让Vue将它转化为响应式的。

需求要在一个对象里面添加一个属性

<!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="./vue.js"></script>
</head>
<body>
  <div id="app">
    <h1>{{obj.a}}</h1>
    <h1>{{obj.c}}</h1>
     <button @click="fn"></button>
  </div>
  <script>
    const app=new Vue({
      el:"#app",
      
      data() {
        return {
          obj:{a:1}
        }
      },

      methods: {
        fn(){
          // this.obj.a=10    // 直接修改原始的对象是可以修改的
          // this.obj.c=10      // 但是想要直接给对象添加一个属性是不可以的
          // this.$set(this.obj,'c',10)   可以利用官方提供的api
        }
      },
    })
  </script>
</body>
</html>

在原始有的对象里直接通过:

? // this.obj.c=10,添加一个属是无效的,

但是可以提供Vue提供的api:

? // this.$set(this.obj,'c',10)?

剖析:this.$set(要添加的对象,属性名(要用字符串包裹起来),属性值)

(3)对于数组

1.对于数组除了一些数组的api:push,pop,unshift,shift等api是响应的之外

2.也可以使用this.$set提供的这个api,在数组中的配置如下:

this.$set(要修改的数组,索引的位置,要添加的元素)

四.实现一个响应式

1.代码

<!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>
</head>
<body>
  <div id="app">
   <!-- 显示obj.a的值 -->
   1
  </div>
  <script>
    var  obj={a:1}
    Object.defineProperty(obj,'a',{
      get:function(){
        console.log(`有人对a属性进行了访问`);
      },
      set:function(newVal){
        document.getElementById('app').innerHTML=newVal
      }
    })
  </script>
</body>
</html>

2.图示

当有人访问到了a属性就会触发get这个函数

?

当有人给a进行赋值的时候就会触发set这个函数

?这个时候可以看见左边的视图发生了改变,符合Vue双向数据绑定的原理,即:数据------------视图,也可以的到的是newVal的值是我们输入的值是10。

五:Object.defineProperty的一些参数

1.Value

 let obj={
      a:1
    }

    Object.defineProperty(obj,'c',{
      value:10
    })
    
    console.log(obj);

图示:

可以看出obj对象里面多出了c属性并且它的值为10,相当于obj.c=10;

2.writable

定于:如果writable的值为false的话,则里面的值是不可以进行修改的、

代码:

<!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>
</head>
<body>
  <script>
    let obj={
      a:1
    }

    Object.defineProperty(obj,'c',{
      writable:false,
      value:10
    })
    
    obj.a=1000     
    obj.c=50  //   用defineProperty修改里面的值是没用效果的
    console.log(obj);
    
  </script>
  
</body>
</html>

图示:

3.configurable

1.configurable:false,表示不能被删除,也不能被重定义。

2.代码

<!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>
</head>
<body>
  <script>
    let obj={
      a:1
    }

    Object.defineProperty(obj,'c',{
      // writable:false,
      value:10,
      configurable:false
    })
    delete obj.a  //可以被删除
    delete obj.c //不能被删除
    
    //   用defineProperty修改里面的值是没用效果的
    console.log(obj);

  </script>
  
</body>
</html>

3.图示:

4.不能被重定义:

<!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>
</head>
<body>
  <script>
    let obj={
      a:1
    }

    Object.defineProperty(obj,'c',{
      // writable:false,
      value:10,
      configurable:false
    })
  // 不能重新进行定义
   Object.defineProperty(obj,'c',{
     value:30
   })


    console.log(obj);

  </script>
  
</body>
</html>

图示:

4.enumerable

定义:如果该值为false的话,则表示是不可以进行枚举的。

代码:

<!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>
</head>
<body>
  <script>
  var person = {}

 Object.defineProperty(person,'name',{
    configurable:false,//能否使用delete、能否需改属性特性、或能否修改访问器属性、,false为不可重新定义,默认值为true
    enumerable:false,//对象属性是否可通过for-in循环,flase为不可循环,默认值为true
    writable:false,//对象属性是否可修改,flase为不可修改,默认值为true
    value:'xiaoming' //对象属性的默认值,默认值为undefined

});

for(var i in person){
    console.log(person[i]) //无结果,不可循环
 }
  </script>
  
</body>
</html>

图示:当为enumerable的时候可以遍历出来

六.封装一个函数,监听对象的属性值变化。

1.代码

<!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>
</head>
<body>
  <script>
    let obj={a:1,b:2,c:3}
    let newObj={}
    for (let key in obj) {
      Object.defineProperty(newObj,key,{
        set:function(newVal){
          console.log(`有人修改了${key},新值是${newVal}`);
       obj[key]=newVal
        },
        get:function(){
          return obj[key]
        }
      })    
    }
  </script>
  
</body>
</html>

2.用了set会被当成拦截器,获取不了值,需要设置变量来解决问题

3.图示:

?七.扩展obj[`key`],obj[key],obj.key的用法和区别

代码:

<!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>
</head>
<body>
  <script>
    let obj={
      name:'卡卡西'
    }
    console.log(obj[`name`]);

    console.log(obj.name);
    
    for (let key in obj) {
    console.log(obj[key]);
    }
  </script>
  
</body>
</html>

对象的属性名是一个字符

验证:

<!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>
</head>
<body>
  <script>
    let obj={
      name:'卡卡西',
      age:20
    }

 console.log(obj[`name`]);
// 所以取出对象属性值的时候,还可以这样写obj[`name`]
for (let key in obj) {
 console.log(typeof key);
}
  </script>
  
</body>
</html>

图示:

?

可以看出分为两种进行使用:

去除对象的属性值:对象.属性名,对象.[`属性名`]

如果需要进行枚举的话:对象[属性名]

列如:

<!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>
</head>
<body>
  <script>
    let obj={
      name:'卡卡西',
      age:20
    }
    for (const key in obj) {
      console.log(key);
      console.log(obj[key]);
    }
  </script>
  
</body>
</html>
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-17 11:25:24  更:2022-01-17 11:27:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:24:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码