精华内容
下载资源
问答
  • 如何监听JS变量变化

    万次阅读 2018-03-05 17:51:24
    我现在有这样一个需求,需要监控js的某个变量的改变, 如果该变量发生变化,则触发一些事件, 不能使用timeinterval之类的定时去监控的方法, 不知道有比较好的解决方案么?这个问题问的很好。流行的MVVM的JS库/框架...

    如何监听JS变量的变化

    如何监听 js 中变量的变化?

    我现在有这样一个需求,需要监控js的某个变量的改变, 如果该变量发生变化,则触发一些事件, 不能使用timeinterval之类的定时去监控的方法, 不知道有比较好的解决方案么?

    这个问题问的很好。

    流行的MVVMJS库/框架都有共同的特点就是数据绑定, 在数据变更后响应式的自动进行相关计算并变更DOM展现。 所以这个问题也可以理解为如何实现MVVM库/框架的数据绑定。

    常见的数据绑定的实现有脏值检测, 基于ES5gettersetter,以及ES已被废弃的Object.observe, 和ES6中添加的Proxy

    脏值检测

    angular使用的就是脏值检测,原理是比较新值和旧值, 当值真的发生改变时再去更改DOM,所以angular中有一个$digest。 那么为什么在像ng-click这样的内置指令在触发后会自动变更呢? 原理也很简单,在ng-click这样的内置指令中最后追加了$digest

    简易的实现一个脏值检测:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title>two-way binding</title>
        </head>
        <body onload="init()">
            <button ng-click="inc">
                Increase
            </button>
            <button ng-click="reset">
                Reset
            </button>
            <span style="color:red" ng-bind="counter"></span>
            <span style="color:blue" ng-bind="counter"></span>
            <span style="color:green" ng-bind="counter"></span>
            <script type="text/javascript">
                /* 数据模型区开始 */
                var counter = 0;
                function inc() {
                    counter++;
                }
                function reset() {
                    counter = 0;
                }
                /* 数据模型区结束 */
                /* 绑定关系区开始 */
                function init() {
                    bind();
                }
                function bind() {
                    var list = document.querySelectorAll("[ng-click]");
                    for (var i=0; i<list.length; i++) {
                        list[i].onclick = (function(index) {
                            return function() {
                                window[list[index].getAttribute("ng-click")]();
                                apply();
                            };
                        })(i);
                    }
                }
                function apply() {
                    var list = document.querySelectorAll("[ng-bind='counter']");
                    for (var i=0; i<list.length; i++) {
                        if (list[i].innerHTML != counter) {
                            list[i].innerHTML = counter;
                        }
                    }
                }
                /* 绑定关系区结束 */
            </script>
        </body>
    </html>
    

    这样做的坏处是自己变更数据后,是无法自动改变DOM的, 必须要想办法触发apply(),所以只能借助ng-click的包装, 在ng-click中包含真实的click事件监听并追加脏值检测以判断是否要更新DOM

    另外一个坏处是如果不注意,每次脏值检测会检测大量的数据, 而很多数据是没有检测的必要的,容易影响性能。

    关于如何实现一个和angular一样的脏值检测,知道原理后还有很多工作要去做, 以及如何优化等等。如果有兴趣可以看看民工叔曾经推荐的《Build Your Own Angular.js》, 第一章Scope便讲了如何实现angular的作用域和脏值检测。 对了,上面的例子也是从民工叔的博客稍加修改来的,建议最后去看下原文,链接在参考资料中。

    ES5的gettersetter

    ES5中新增了一个Object.defineProperty, 直接在一个对象上定义一个新属性, 或者修改一个已经存在的属性,并返回这个对象。

    Object.defineProperty(obj, prop, descriptor)
    

    其接受的第三个参数可以取getset并各自对应一个gettersetter方法:

    var a = { zhihu:0 };
    Object.defineProperty(a, 'zhihu', {
      get: function() {
        console.log('get:' + zhihu);
        return zhihu;
      },
      set: function(value) {
        zhihu = value;
        console.log('set:' + zhihu);
      }
    });
    a.zhihu = 2; // set:2
    console.log(a.zhihu); // get:2
                          // 2
    

    基于ES5gettersetter可以说几乎完美符合了要求。为什么要说几乎呢?

    首先IE8及更低版本IE是无法使用的,而且这个特性是没有polyfill的, 无法在不支持的平台实现, 这也是基于ES5 gettersetterVue.js不支持IE8及更低版本IE的原因。 也许有人会提到avalon, avalon在低版本IE借助vbscript一些黑魔法实现了类似的功能。

    除此之外,还有一个问题就是修改数组的length, 直接用索引设置元素如 items[0] = {}, 以及数组的push等变异方法是无法触发setter的。 如果想要解决这个问题可以参考Vue的做法, 在Vueobserver/array.js中,Vue直接修改了数组的原型方法:

    const arrayProto = Array.prototype
    export const arrayMethods = Object.create(arrayProto)
    /**
     * Intercept mutating methods and emit events
     */
    ;[
      'push',
      'pop',
      'shift',
      'unshift',
      'splice',
      'sort',
      'reverse'
    ]
    .forEach(function (method) {
      // cache original method
      var original = arrayProto[method]
      def(arrayMethods, method, function mutator () {
        // avoid leaking arguments:
        // http://jsperf.com/closure-with-arguments
        var i = arguments.length
        var args = new Array(i)
        while (i--) {
          args[i] = arguments[i]
        }
        var result = original.apply(this, args)
        var ob = this.__ob__
        var inserted
        switch (method) {
          case 'push':
            inserted = args
            break
          case 'unshift':
            inserted = args
            break
          case 'splice':
            inserted = args.slice(2)
            break
        }
        if (inserted) ob.observeArray(inserted)
        // notify change
        ob.dep.notify()
        return result
      })
    });
    

    这样重写了原型方法,在执行数组变异方法后依然能够触发视图的更新。

    但是这样还是不能解决修改数组的length和直接用索引设置元素如items[0] = {}的问题, 想要解决依然可以参考Vue的做法: 前一个问题可以直接用新的数组代替旧的数组; 后一个问题可以为数组拓展一个$set方法, 在执行修改后顺便触发视图的更新。

    已被废弃的Object.observe

    Object.observe曾在ES7的草案中,并在提议中进展到stage2,最终依然被废弃。 这里只举一个MDN上的例子:

    // 一个数据模型
    var user = {
      id: 0,
      name: 'Brendan Eich',
      title: 'Mr.'
    };
    // 创建用户的greeting
    function updateGreeting() {
      user.greeting = 'Hello, ' + user.title + ' ' + user.name + '!';
    }
    updateGreeting();
    Object.observe(user, function(changes) {
      changes.forEach(function(change) {
        // 当name或title属性改变时, 更新greeting
        if (change.name === 'name' || change.name === 'title') {
          updateGreeting();
        }
      });
    });
    

    由于是已经废弃了的特性,Chrome虽然曾经支持但也已经废弃了支持, 这里不再讲更多,有兴趣可以搜一搜以前的文章, 这曾经是一个被看好的特性(Object.observe()带来的数据绑定变革)。 当然关于它也有一些替代品Polymer/observe-js

    ES6带来的Proxy

    人如其名,类似HTTP中的代理:

    var p = new Proxy(target, handler);
    

    target为目标对象,可以是任意类型的对象,比如数组,函数,甚至是另外一个代理对象。 handler为处理器对象,包含了一组代理方法,分别控制所生成代理对象的各种行为。

    举个例子:

    let a = new Proxy({}, {
      set: function(obj, prop, value) {
        obj[prop] = value;
        if (prop === 'zhihu') {
          console.log("set " + prop + ": " + obj[prop]);
        }
        return true;
      }
    });
    a.zhihu = 100;
    

    当然,Proxy的能力远不止此,还可以实现代理转发等等。

    但是要注意的是目前浏览器中只有Firefox 18支持这个特性, 而babel官方也表明不支持这个特性:

    Unsupported feature
    Due to the limitations of ES5, Proxies cannot be transpiled or polyfilled.
    

    目前已经有babel插件可以实现,但是据说实现的比较复杂。 如果是Node的话升级到目前的最新版本应该就可以使用了,上面的例子测试环境为 Node v6.4.0

    参考资料

    展开全文
  • 为什么没有变化,主要你通过数据不是响应式,没有被Vue监控.首先这么改动下就可以了{{list}}{{postList}}export default {data() {return {list: [],postList: {}}},created:function(){var result = {list: [{"tems13...

    为什么没有变化,主要你通过数据不是响应式,没有被Vue监控.

    首先这么改动下就可以了

    {{list}}{{postList}}

    export default {

    data() {

    return {

    list: [],

    postList: {}

    }

    },

    created:function(){

    var result = {

    list: [

    {"tems13Gtoup": 0},

    {"tems13Gtoup": 1},

    {"tems13Gtoup": 2},

    {"tems13Gtoup": 3}

    ]

    }

    result.list.forEach((item, index)=>{

    if(!this.list[item.tems13Gtoup]){

    this.$set(this.list, item.tems13Gtoup, []);

    }

    this.list[item.tems13Gtoup].push(item);

    });

    var result2 = {

    list: [

    {"tems13Gtoup": "A"},

    {"tems13Gtoup": "B"},

    {"tems13Gtoup": "C"},

    {"tems13Gtoup": "D"}

    ]

    }

    result2.list.forEach((item, index)=>{

    if(!this.postList[item.tems13Gtoup]){

    this.$set(this.postList, item.tems13Gtoup, 0);

    }

    });

    }

    }

    主要通过 $set 把数据定义为响应式, 并给 vm监测, 当数据变化时 vm 自动更新视图; vm 指的 Vue 的实例(对应 export default {}).

    在给 list 赋值时, 为什么 tems13Gtoup改为数值, 数组已数值作为索引. 如果需要字母和中文可以使用对象替代也就下面的 postList 方式({});

    vm.$set( target, propertyName/index, value )

    {Object | Array} target

    {string | number} propertyName/index

    {any} value

    展开全文
  • 用vue.js过程中了解到计算属性,它类似于定义了一个函数f,f的返回值依赖于某些变量a,b,c。当a,b,c中任意一个发生变化,就调用f得到新的返回值。 我现在用token做登录身份验证,使用到localStorage,在computed中...

    https://segmentfault.com/q/1010000006806036

     

    1.问题

    用vue.js过程中了解到计算属性,它类似于定义了一个函数f,f的返回值依赖于某些变量a,b,c。当a,b,c中任意一个发生变化,就调用f得到新的返回值。

    我现在用token做登录身份验证,使用到localStorage,在computed中编写“函数”,根据localStorage的值,在导航栏显示不同的链接:已经登录的显示“用户名”和“退出”,未登录则显示“注册”和“登录”。

    我发现computed中编写的“函数”不会监控localStorage取值的变化:当我将localStorage清空后,页面并没有根据相应的条件,改变导航栏的显示。

    问题:vuejs能否监控localStorage取值的变化?如果能,代码怎么写?如果不能,有哪些推荐方案?

    2.代码

    我的导航栏组件代码headnav.vue:

    <template>
        <!-- Fixed navbar -->
        <nav class="navbar navbar-inverse navbar-fixed-top" id="navbarcolor">
          <div class="container-fluid">
            <div class="navbar-header">
              <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
              </button>
              <a href="/" class="navbar-left"><img src="../../assets/rlogo2.png" style="height:43px;margin:auto;margin-right:20px"></a>
            </div>
            <div id="navbar" class="navbar-collapse collapse">
              <ul class="nav navbar-nav" id="navtext">
                <li></li>
                <li>
                  <ul class="dropdown-menu">
                    <li><a href="#">我的网站</a></li>
                  </ul>
                </li>
              </ul>
              <ul class="nav navbar-nav navbar-right" v-if="signed">            
                <li><a href="sss">{{sign_name}}</a></li> <li><a @click="logout">退出</a></li>;
              </ul>
              <ul class="nav navbar-nav navbar-right" v-else>
                <li><a v-link="{ path: 'login' }">登录</a></li> <li><a href="register.html">注册</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </nav>
    </template>
    
    <script>
    export default {
      data () {
        return {
          sign_name: '' // 已登录时的用户名
        }
      },
      computed: {
        // 这里!判断是否已经登录
        // 但是发现不能监控localStorage的变化
        signed () {
          if (localStorage.token != null) {
            return true
          }
          return false
        }
      },
      methods: {
        logout () {
          localStorage.clear() // 清空localStorage
        }
      }
    }
    </script>

    3.报错

    也不算是大的错误,但是当点击“退出”后,页面导航栏的内容并不更新。

    4.已有尝试

    在组件的export default中编写了ready()方法,让页面每次加载的时候把localStorage变量存储在一个变量sign_name中,以后用这个变量sign_name来判断用户是否登录。但是这样做感觉比较麻烦的样子。

     

    3个回答

    答案对人有帮助,有参考价值2答案没帮助,是错误的答案,答非所问

    已采纳

    所有localStorage操作都通过vuex实现

    答案对人有帮助,有参考价值1答案没帮助,是错误的答案,答非所问

    自己补充一个回答,高手请忽略,小白作为参考。

    用vuex可以维护多个组件之间的共用信息,有点“全局变量”的意思。

    不过我这里要在多个tab之间维护同样的登录状态,还需要配合js的事件监听函数来做。例如我把vuex脚手架搭起来,登录信息的改变相关的action和mutation都写好了,那么还需要在store.js中监听storage的变化:

    // 用来维护多个标签页之间登录信息的同步
    var storageHandler = function () {
      state.loginName = localStorage.name
    }
    window.addEventListener('storage', storageHandler, false)

    参考:
    Vuex: Syncing state between 2 tabs
    Responding to storage changes with the StorageEvent
    Event对象

    答案对人有帮助,有参考价值0答案没帮助,是错误的答案,答非所问

    Vue 仅可以对其管理的数据做响应式处理,可以理解为 data 中的数据,localStorage 并不在 Vue 的管理下,自然不会有响应特性。要响应 localStorage 的变化,可以尝试 onStorage 事件。

    转载于:https://www.cnblogs.com/zaifeng0108/p/7226450.html

    展开全文
  • 前言 某联招聘网站使用了5版本的某数作为反爬措施,某数的机制...这个动态js每次访问页面都会重新生成,虽然是重新生成的,但其内部代码逻辑不变,行号也不会变化,唯一变化的就是变量的名称,当然这个变量名称其实是

    仅供学术研究,如有侵权请即时通知,文章会在第一时间内删除!

    前言

    某联招聘网站使用了5版本的某数作为反爬措施,某数的机制基本上都是页面中js代码结合一个iso-8859-1编码的js文件来生成动态js,通过eval的形式执行该动态js,动态js在初始化阶段会读取页面meta中的content内容进行一些参数的初始化,动态js和页面js中还会有相互调用的情况,动态js做了混淆、平坦化、反调试、浏览器校验、鼠标键盘监控等等工作。

    这个动态js每次访问页面都会重新生成,虽然是重新生成的,但其内部代码逻辑不变,行号也不会变化,唯一变化的就是变量的名称,当然这个变量名称其实是通过$_ts全局变量中一个变量池数组来控制的。

    如果是翻页或者页面内点击链接,不会重新请求页面,而是直接发起ajax请求,在发起ajax请求的时候,这个动态js会对xhr进行hook,在url末尾添加 MmEwMD=5xx 的参数,服务器会校验这个参数是否符合规则、是否在有效期、是否第一次使用,通过校验就会返回响应的json数据。

    当然这个参数的生成逻辑还是很复杂的,10000多行的代码我生生的给简化到1000行,并能正常生成可”无毒食用“的MmEwMD=参数了,后续会将总体方案介绍写出来供交流学习。

    今天先分享动态js如何在初始化阶段调试的方案!

    动态js在eval执行时的调试方案

    由于动态js在初始化阶段,也就是第一次eval阶段做了很多工作,为了弄清楚他的逻辑,需要在初始化阶段进行断点调试,但是在eval阶段又看不到代码无法加断点,如何进行调试呢?

    一个简单易用的方案如下:

    1. 使用chrome拦截XHR
      访问任一职位列表页面,在chrome浏览器的开发者工具中勾选Any XHR or fetch拦截请求。 (执行完会清理代码,有可能在页面中找不到对应的代码,所以要先拦截)image-20200506205725891.png

    2. 然后清空站点数据
      把该站点的所以数据都清空。image-20200506205754490.png

    3. F5刷新访问,对页面js格式化
      刷新浏览器,重新访问页面,这时就会看到请求被断点拦截了,然后找到当前页面,使用chrome的格式化功能对页面的js进行格式化image-20200506210015633.png

    4. 页面js代码添加断点
      然后在格式化的js中搜索 ret = ,找到第二处加断点image-20200506210218792.png

    5. 再次刷新页面在eval的字符串前添加debugger;
      然后去掉XHR的拦截后,再次刷新页面,因为这个页面的代码每次也是会变化的,所以对应的断点可能不正确了,没关系,再次搜索到 ret = 加上端点就可以了,然后F8会在这个call的地方(其实就是eval的地方)断下来了。
      在控制台运行命令 _$cu="debugger;"+_$cu (注意变量名称每次都会变化的)
      image-20200506210536399.png

    6. F8进入动态js的初始化断点
      然后在F8就可以看到在动态js的开始位置断点停下了,对动态js代码进行格式化后,就可以愉快的进行首次初始化的跟踪调试了。
      image-20200506210612754.png

    展开全文
  • 在App.vue的script标签中,有三部分内容,分别是data(用来存放数据的变量),methods(被调用的方法),watch(监控页面某个变量变化产生相应的变化) 1.首先,用v-html来获取data中title的数据 2.v-for对items中...
  • computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是说多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化,举例:购物车里面的商品列表和总金额之间的关系,只要商品列表里面的...
  • 时间、环境等系统变量来确定不同的展现 - 管理前端资源和依赖 我们在 xtemplate 模板引擎的基础上进行扩展,让前端通过编写 xtemplate 模板,在 context 中注入一些必需的页面上下文,扩展 ...
  • PHP5调试工具debugConsole

    千次阅读 2011-12-23 09:01:45
    监控变量,跟踪变量的变化,打断点,记录日志,这些功能都有,在运行的时候直接这些数据输出到一个js生成的弹窗里,工具地址 http://www.debugconsole.de/
  • 对动态js的效果修改的话先把鼠标放置到上面触发效果,然后右键点击,选择检查即可 ...右键某个想监控变量,add to watch可以监控他的变化 第五个表示取消所有断点,再次点击可以恢复 第六个打钩表示直
  • observable()方法,用于设置监控属性,这样就可以监控viewModule中的属性值的变化,从而就可以动态的改变某个元素中的值,监控属性的类型不变量而是一个函数,通过返回一个函数给viewModule对象中的属性,从而来监控...
  • vue中的watch用法

    2019-09-25 10:55:56
    VUE官方文档: vm.$watch API vue侦听器 Vue.js 提供了一个方法 watch,它用于观察Vue实例上的数据...键是观察表达式,就是要监控的对象,比如说$route,这个就是要监控路由的变化。或者是data中的某个变量。 ...
  • 随着组件的细化,就会遇到多组件...observable()方法,用于设置监控属性,这样就可以监控viewModule中的属性值的变化,从而就可以动态的改变某个元素中的值,监控属性的类型不变量而是一个函数,通过返回一个函数给vie
  • 度量标准、编码优化、静态资源优化、交付优化、构建优化、性能监控。 <p><img src="https://img-blog.csdnimg.cn/img_convert/14ad1f908e0ef1eb728b52e27c2aae9b.png" alt="优化分类" width="612" /> 图1. 性能优化...
  • <div><p>原文地址</a></p> 深入理解 webpack 文件打包机制 前言 最近在重拾 webpack 一些知识点,...这段初始化时代码就会发生变化,那么如果将这段初始化代码放在 vendor 文件中的话,每次都会生成新...
  • 33.数据变更记录日志,可记录数据每次变更内容,通过版本对比功能查看历史变化 34.平台UI强大,实现了移动自适应 35.平台首页风格,提供多种组合模式,支持自定义风格 36.提供简单易用的打印插件,支持谷歌、火狐、...
  • // 声明变量管理vue及路由实例 let router = null; let instance = null; // 导出子应用生命周期 挂载前 export async function bootstrap(props) { console.log(props) } // 导出子应用生命周期 挂载前 挂载后 *...
  • 修改 Ant Design 配色,在文件 vue.config.js 中,其他 less 变量覆盖参考 ant design 官方说明 css: { loaderOptions: { less: { modifyVars: { /* less 变量覆盖,用于自定义 ant design 主题 */ '...
  • 每一次前端开发模式的变化,都因某个变革性的技术而起。先是 AJAX,而后是 Node.js。那么下一个变革性的技术是什么?不言而喻,就是 Serverless。 <p><a name="9222c252"></a></p> <h2>...
  • 注:本系列图书的第I、II卷再版时均相应改名为《xxx开发实例大全》(基础卷)及(提高卷),但内容基本无变化,需要的童鞋可自由匹配查找。 内容简介  《Java Web开发实战1200例》分为I、II两卷共计1200个例子,包括了...
  • │ 第49节:VCL的变量和常见的应用片断.avi │ 第50节:使用CLI来管理Varnish.avi │ 第51节:Varnishd命令和运行期参数.avi │ 第52节:Varnish的日志操作.avi │ 第53节:规划缓存大小和提高命中率.avi │ 第54节...
  • C++ 资源大全中文版 awesome-cpp 就是 fffaraz 发起维护的 C++ 资源列表,内容包括:标准库、Web应用框架、人工智能、数据库、图片处理、机器学习、日志、代码分析等。 中文版由开源前哨和CPP开发者微信公号团队维护...

空空如也

空空如也

1 2
收藏数 26
精华内容 10
关键字:

js监控变量变化