20230624----重返学习-vue-响应式处理思路-仿源码

news/2024/11/7 13:33:08/

day-098-ninety-eight-20230624-vue-响应式处理思路-仿源码

vue

vue大体概念

  • Vue是渐进式框架

    • 所谓渐进式框架,就是把一套全面的框架设计体系,拆分成为多个框架,项目中需要用到那些需求,再导入对应的框架,以此来保证外部资源的最小化!
  • Vue2全家桶

    • Vue@2:vue框架的核心!含单个组件状态管理、组件的管理。
      • vue-cli:用于创建项目的脚手架工具。管控webpack等打包功能。
    • vuex@3:实现vue组件间的公共状态管理。
      • vuex-persist 公共状态持久化存储插件。
    • vue-router@3:SPA单页面应用中的路由管理!
    • UI组件库:
      • PC端:饿了么团队element-ui、阿里antd of vue@1、京东iview。
      • 移动端:有赞vant@2、蚂蚁金服cube…
  • Vue3全家桶

    • vue@3
      • vite:用于创建项目的脚手架工具。
    • vuex@4、pinia
    • vue-router@4
    • UI组件库:
      • PC端:element-plus、antd of vue@3…
      • 移动端:vant@3…
  • Vue生态中,完善的项目解决方案:

    • antd pro vue:淘系方案-核心是vue3。
      • pro.antdv官网
      • 免费版:pro.antdv文档
      • 收费版:vue3 + TS
    • 若依
      • 若依-官网

vue常见面试题

  • Vue2框架常见的面试题
    1. 谈谈你对 MVVM / MVC 模式的理解
    2. Vue2框架怎么实现对象和数组的监听?「Vue2响应式原理」
    3. v-model指令实现的原理
    4. v-show 与 v-if 有什么区别?
    5. Class 与 Style 如何动态绑定?
    6. computed 和 watch 的区别和运用的场景?
    7. 谈谈你对 Vue2 生命周期的理解?
    8. Vue怎么用 vm.$set() 解决对象新增属性不能响应的问题 ?
    9. 开发中常用的Vue指令有哪些

MVVM与MVC

  • 面试题:谈谈你对 MVVM / MVC 模式的理解?
    • MVVM模式:双向数据驱动,如Vue2与Vue3。

      • model:数据层。

        • 在数据层,我们需要构建出:项目中需要的各种数据与方法。例如:响应式状态、属性、计算属性、监听器、过滤器、方法、钩子函数…
          • 说明:
            • 在vue2中:基于OptionsAPI(配置项)方式,来管理这些内容。

              export default {data(){ return { ... } },props:[...],computed:{},watch:{},filters:{},methods:{},...
              }
              
              <script>
              export default {data(){ return { ...响应式状态 } },props:[...属性],computed:{...计算属性},watch:{...监听器},filters:{...过滤器},methods:{...方法},...
              }
              </script>
              
            • vue3中:基于CompositionAPI(聚合式)&函数式编程方式,来管理这些内容。

      • view 视图层。

        • 视图层的原理:在Vue框架中,我们基于<template>jsx语法构建需要的视图,最后把视图编译为VirtualDOM(虚拟DOM),再经过DOM-diff进行差异化对比,最后把VirtualDOM/补丁包渲染为真实的DOM
          • 步骤说明:
            1. 基于<template>jsx语法构建需要的视图。
              • 这个主要是用户自己手写的,绑定响应式数据与绑定事件。
              • 还基于指令控制数据与视图的联系。
            2. 视图编译为VirtualDOM
              • 在vue2中:基于vue-template-compiler插件,把视图编译为VirtualDOM
              • 在vue3中:基于@vue/compiler-sfc插件,把视图编译为VirtualDOM
            3. 经过DOM-diff进行差异化对比。
              • 这个是vue内部做的,diff算法。
            4. VirtualDOM/补丁包渲染为真实的DOM
              • 渲染周期步骤:
                • 第一次渲染VirtualDOM直接渲染为真实的DOM
                • 非初次渲染补丁包渲染为真实的DOM
                  • 补丁包是通过DOM-diff这一步来对比新旧数据来生成的。性能好,能更快渲染。
              • 这一步基本上都是vue内部做的。
      • viewModel:监听层,Vue框架的核心。

        1. 这个是vue框架内部自动做的。正常不用关心。
        • 监听响应式数据的变化,当数据发生改变后,通知视图更新。
          • Vue2中基于Object.defineProperty对数据进行劫持。
          • Vue3中基于ES6中的Proxy对数据进行劫持。
          • 基于观察者模式通知视图更新。
        • 监听视图的变化(一般指的是Form表单内容的改变),当视图内容改变后,自动修改对应的数据(数据一改,视图紧接着跟着更新)。
          • 监听视图变化主要是基于v-model指令。
    • MVC模式:单向数据驱动框架,如React。

      • model 数据层。

        • 构建项目中需要的数据和方法。例如:状态、属性、钩子函数、普通函数等。
          • 类组件中:基于 state/props/实例 构建状态和属性。
          • 函数组件中:基于useState/useEffectHooks函数,完成上述内容的管理。
      • view 视图层。

        • 在React中,基于jsx语法构建需要的视图React会基于babel-preset-react-appjsx语法编译为React.createElement格式createElement方法执行,会创建出对应的VirtualDOM,经过DOM-diff对比,最后把VirtualDOM/补丁包,基于ReactDOM中的render方法,渲染为真实的DOM
      • controller 控制层。

        • 实现事件绑定和相关的业务逻辑。
        • React框架实现了数据更改可以让视图自动更新的机制。但是React不同于Vue,并没有对状态做数据劫持。如果打算修改状态后,让视图更新,需要基于特定的方法去修改状态才可以!
          • 类组件中:可以用setState/forceUpdate方法。
          • 函数组件中,可以用useState等Hook函数。
        • 但是React中默认并没有实现对视图的监听,这样导致,视图内容改变,对应的状态也不会自动更改!
          • 不过我们可以自己给表单元素做事件绑定,当内容改变后,手动去修改对应的状态。
    • 总结:无论是MVVM还是MVC,都是目前前端主流的框架思想,都是以数据驱动视图渲染核心,告别传统直接操作DOM的方式,转而操作VirtualDOM!再配合对应的生态体系,让项目开发既高效,又提高了性能!…

Vue的学习路线

  • 如何学习Vue?
    • 第一条线:视图线
      • <template>JSX语法
        • 指令「内置的14个指令和自定义指令」
        • JSX语法
      • VirtualDOM编译的机制
      • 掌握DOM-DIFF算法
    • 第二条线:数据线
      • 学习 OptionsAPI/CompositionAPI 中的:语法、原理、区别等内容
        1. OptionsAPI选项
      • 学习 MVVM 的原理
        • 数据是如何被监听的「Vue2和Vue3是不一样的」
        • 监听数据变化后,如何通知视图更新「观察者模式」
        • 如何监听视图的变化,以及如何让状态跟着更改「v-model」
    • 第三条线:组件化开发
      • 单文件组件「含样式私有化方案的原理」
      • 类组件和函数组件
      • 复合组件通信
      • 组件封装的技巧「各种封装技巧」
        • 通用业务组件
        • UI组件库的二次封装
        • 通用功能组件
        • Vue.mixin
        • Vue.directive
        • Vue.extend
    • 第四条线:实战线
      • vuex / vue-router
      • <keep-alive>
      • <transition>
      • <component>
      • 上拉刷新、下拉加载
      • 超长列表性能优化
      • 登录/权限管理模型
      • 前后端数据通信管理方案

OptionsAPI选项式数据

  1. OptionsAPI选项-数据
  2. OptionsAPI选项-DOM
  3. OptionsAPI选项-生命周期钩子
  4. OptionsAPI选项-资源
  5. OptionsAPI选项-组合
  6. OptionsAPI选项-其它

对象和数组的监听

  • 面试题:Vue2框架怎么实现对象和数组的监听?「Vue2响应式原理」

数据初始化

  • vue2源码在/node_modules/vue/dist/vue.js中。
  • new Vue()的时候,OptionsAPI中的data是用来构建响应式数据-即状态的。
    • 特点
      1. 在data中构建的状态,会直接挂载到实例上。
        • 在js中,可以基于实例去访问对应的状态 -> vm.msg/this.xxx;
        • 而挂载到实例上的信息,可以直接在视图中访问 -> {{msg}};
      2. 在data中构建的状态,会被进行数据劫持,即get/set。数据劫持的目的是让其变为响应式的,这样以后修改此状态信息,会触发set劫持函数,在此劫持函数中,不仅修改了状态值,而且还会通知视图更新!
        - 只有在new的时候,写在data中的状态,才会默认被数据劫持,变为响应式状态。
    • Vue2响应式源码:
      1. new Vue()后,首先执行Vue.prototype._init方法,在此方法中做了很多事情,例如:
        • 向实例上挂载很多内置的私有属性。
          • 带$xxx是我们开发者后续要用到的。
          • 带_xxx是给Vue内部用的。
        • 基于callHook$1方法,触发beforeCreate()钩子函数执行。
        • 初始化上下文中的信息。
        • 执行initState方法,初始化属性、状态、计算属性、监听器等信息。
        • 触发created钩子函数执行。
      2. 执行initState方法的时候
        • 基于initProps$1初始化属性。注册接收属性与属性规则校验。
        • 基于initMethods初始化普通函数。
        • 基于initComputed$1初始化计算属性。
        • 基于initWatch初始化监听器。
        • 基于initData初始化状态。
      3. 执行initData方法的时候,主要目的就是初始化状态-也就是把信息做响应式数据劫持。
        • 先判断data是否是一个函数(组件中的data都是函数),如果是函数,先把函数执行(函数中的this是实例,并且传递实例),把执行的返回值,重新赋值给data。

          var data = vm.$options.data;
          data = vm._data = isFunction(data) ? getData(data, vm) : data || {};
          
        • 接下来要确保data是一个纯粹的对象。

          if (!isPlainObject(data)) {data = {};warn$2('data functions should return an object:\n' + 'https://v2.vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', vm);
          }
          
        • 然后基于Object.keys方法,获取data对象中的可枚举、非Symbol类型的私有属性,然后判断这些属性,是否出现在methods和props中,如果出现了则报错!原因:methods/pprops中编写的信息,也会直接挂在实例上,如果名字,则相互冲突了!

          var keys = Object.keys(data);
          var props = vm.$options.props;
          var methods = vm.$options.methods;
          var i = keys.length;
          while (i--) {...
          }
          
          var keys = Object.keys(data);
          var props = vm.$options.props;
          var methods = vm.$options.methods;
          var i = keys.length;
          while (i--) {var key = keys[i];{if (methods && hasOwn(methods, key)) {warn$2("Method \"".concat(key, "\" has already been defined as a data property."), vm);}}if (props && hasOwn(props, key)) {warn$2("The data property \"".concat(key, "\" is already declared as a prop. ") +"Use prop default value instead.", vm);}else if (!isReserved(key)) {proxy(vm, "_data", key);}
          }
          
        • 最后基于observe函数,对data对象中的信息进行数据劫持!

          var ob = observe(data);
          ob && ob.vmCount++;
          
        • 学习总结:真实项目中,建议把状态数据,全部事先写在data中(即便不清楚其值,也先写上,可以赋值初始值)。因为只有写在data中的数据,在最开始渲染阶段,才会被做响应式的数据劫持

      4. 执行observe方法的时候,把data对象传递进去。
        • 如果data对象已经被处理过,则不会重新处理。

          if (value && hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {return value.__ob__;
          }
          
        • 而且data对象必须符合好多条件,才可以去处理:是数组或者对象、并且没有被冻结/密封/阻止扩展、并且不是ref对象,也不是VirtualDOM(vnode)…

          if (shouldObserve &&(ssrMockReactivity || !isServerRendering()) &&(isArray(value) || isPlainObject(value)) &&Object.isExtensible(value) &&!value.__v_skip /* ReactiveFlags.SKIP */ &&!isRef(value) &&!(value instanceof VNode)) {return new Observer(value, shallow, ssrMockReactivity);
          }
          

          简洁处理:

          if (... && (isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value.__v_skip  && !isRef(value) && !(value instanceof VNode)) {return new Observer(value, shallow, ssrMockReactivity);
          }
          
        • 如果符合了全部条件,则创建Obsever类的实例,把data对象传递进去进行处理。

        • 学习总结:如果某个写在data中的对象,我们不期望对其内部做劫持处理,此时我们只需要把这个对象基于Object.freeze()冻结即可!

          • 因为劫持处理的过程是需要消耗性能和时间的。
            • 例如:从服务器获取的数据,我们并没有修改其内部某一项值),让视图更新的需求,那么这些数据压根就不需要做劫持。
      5. 执行new Observer(data),对data对象中的每一项进行数据劫持
        • 但凡被处理过的对象,都会设置一个__ob__属性,属性值是Observer类的实例。

          def(value, '__ob__', this);
          
        • 然后判断data是数组还是对象,两者处理的方式是不一样的。

          • 如果是对象:

            • 基于Object.keys()获取对象所有可枚举、非Symbol类型的私有属性。

            • 然后迭代这些成员,对每一个成员,基于defineReactive()做数据劫持。

              var keys = Object.keys(value);
              for (var i = 0; i < keys.length; i++) {var key = keys[i];defineReactive(value, key, NO_INIITIAL_VALUE, undefined, shallow, mock);
              }
              
          • 如果是数组:

            • 在Vue2中,有一个对象arrayMethods,这个对象的特点:
              • 对象中有7个方法:push/pop/shift/unshift/splice/sort/reverse;
              • 对象.__proto__指向Array.prototype
            • 接下来让data这个数组,拥有arrayMethods上的这七个方法。
              • 在非IE浏览器中,就是让 data数组.__proto__=arrayMethods
              • 在IE浏览器中,迭代arrayMethods中的每一个方法,把这些方法作为data数组的私有方法。
            • 当我们以后调用数组这7个方法的时候,用的都是arrayMethods中的这七个方法。
              • 调用重写的这7个方法,其内部:
                • 获取传递的实参。
                • 基于Array.prototype内置的方法实现对应的功能。
                • 如果调用的是push/unshift/splice,需要把新增的内容,基于observeArray进行递归处理,实现深度的监听劫持。
                • 最后通知视图更新。
            • 执行observeArray对传递的data数组,再次进行递归处理。
      6. 在defineReactive函数中。
        • 首先又对此对象中的某个成员进行校验,验证是否是冻结/密封的,如果是,则不进行数据劫持。

          var property = Object.getOwnPropertyDescriptor(obj, key);
          if (property && property.configurable === false) {return;
          }
          
        • 然后对对象中此成员的值,进行递归处理,目的是进行尝试的监听劫持!

          var childOb = !shallow && observe(val, false, mock);
          
        • 最后基于Object.defineProperty()对此对象中的这个成员做get/set劫持。

      7. 在observeArray方法中:
        • 迭代数组中的每一项,对每一项再基于observe进行递归处理,实现深度的监听劫持。

          for (var i = 0, l = value.length; i < l; i++) {observe(value[i], false, this.mock);
          }
          
          • 深度的监听劫持:

            let vm = new Vue({data: {msg: "哈哈",obj:{x:10,}},
            });
            
            • 不仅对msgobj做了数据劫持,还对obj这个对象的x属性也做了数据劫持
      • 总结:Vue2响应式原理,针对数组和对象,有不同的处理情况:
        • 如果是对象:基于Object.defineProperty对对象中的每个成员(成员特点是可枚举、非Symbol类型),进行深度的监听劫持。
          • 当修改成员值的时候,触发set劫持函数。在set函数中,不仅修改了成员值,而且还对新修改的值做监听劫持。最主要的是通知视图更新!
        • 如果是数组:并不像对象一样,没有对数组中的每个索引项做监听劫持。所以基于索引修改数组某一项的值,视图是不会更新的。而是重写了数组的7个方法-push/shift/unshift/pop/splice/sort/reverse,基于这7个方法修改数组的内容,不仅仅修改了内容,而且对新修改的内容也会做劫持,也会通知视图的更新!最后对数组中的每一项内容,也基于递归的方式,看看是否需要劫持!
      • 代码示例:
        • fang/f20230624/day0624/test.html

          <!DOCTYPE html>
          <html><head><meta charset="UTF-8" /><title>Document</title></head><body><div id="app">{{msg}}-{{text}}</div></body>
          </html>
          <!-- <script src="./node_modules/vue/dist/vue.min.js"></script> -->
          <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
          <script>let vm = new Vue({data: {msg: "哈哈",},});vm.text = "嘿嘿";console.log(`实例:vm-->`, vm);setTimeout(() => {vm.text = "hhh";console.log(2000, `text改值了,但视图并没有自动更新`);}, 2000);setTimeout(() => {vm.msg = "方";console.log(10000, `msg改值了,但视图会自动更新`);}, 10000);vm.$mount("#app");
          </script>
          

响应式处理思路-仿源码

  • fang/f20230624/day0624/test.html

    <!DOCTYPE html>
    <html><head><meta charset="UTF-8" /><title>Document</title></head><body><div id="app">{{msg}}-{{text}}</div></body>
    </html>
    <!-- <script src="./node_modules/vue/dist/vue.min.js"></script> -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> -->
    <script>// let vm = new Vue({//   data: {//     msg: "哈哈",//     obj:{//       x:10,//     }//   },// });// vm.text = "嘿嘿";// console.log(`实例:vm-->`, vm);// setTimeout(() => {//   vm.text = "hhh";//   console.log(2000, `text改值了,但视图并没有自动更新`);// }, 2000);// setTimeout(() => {//   vm.msg = "方";//   console.log(10000, `msg改值了,但视图会自动更新`);// }, 10000);// vm.$mount("#app");
    </script><script src="./test.js"></script>
    
  • fang/f20230624/day0624/test.js

    // 检测是否为纯粹对象。
    const toString = Object.prototype.toString;
    const isPlainObject = function isPlainObject(obj) {if (toString.call(obj) !== "[object Object]") return false;let proto = Object.getPrototypeOf(obj);if (!proto) return true;let Ctor = "constructor" in obj && obj.constructor;return Ctor === Object;
    };// 给对象设置不可枚举的属性。
    const define = function define(obj, key, value) {Object.defineProperty(obj, key, {value,enumerable: false,writable: true,configurable: true,});return obj;
    };// 通知视图更新的方法。
    const notify = function notify() {console.log(`视图更新`);
    };// 重写数组7个方法的对象。
    const arrayProto = Array.prototype;
    const arrayMethods = Object.create(arrayProto);
    let methods = ["push", "pop", "shift", "unshift", "splice", "sort", "reverse"];
    methods.forEach((method) => {let original = arrayProto[method]; //对应Array.prototype上的内置方法。define(arrayMethods, method, function mutator(...args) {// 基于内置的方法,把功能先实现。this-我们要操作的数组let result = original.call(this, ...args);// 对于新增或修改的信息,需要基于递归,进行深层次的监听劫持。let inserted;switch (method) {case "push":case "unshift":inserted = args;break;case "splice":inserted = args.slice(2);break;default:break;}if (inserted) {observeArray(inserted);}// 通知视图更新。notify();return result;});
    });
    // ary.push(100, 200, 300);// 数据劫持的处理。
    const defineReactive = function defineReactive(obj, key, proxy) {// 对成员的规则再次校验。let property = Object.getOwnPropertyDescriptor(obj, key);if (property && property.configurable === false) {return;}// 对此成员的值进行深度处理。observe(obj[key]);// 对此成员进行数据劫持。Object.defineProperty(obj, key, {get: function reactiveGetter() {return proxy[key];},set: function reactiveSetter(newVal) {// 新老值相同,则不进行任何的处理。if (Object.is(newVal, obj[key])) {return;}// 修改值proxy[key] = newVal;// 对新设置的值也要进行深度处理。observe(newVal);// 通知视图更新notify();},});
    };// 对数组中的每一项进行响应式处理。
    const observeArray = function observeArray(arr) {// 对传递数组中的每一项,都基于observe进行响应式处理。// debugger;arr.forEach((item) => {observe(item);});
    };
    // 对数组/对象进行响应式处理。
    const observe = function observe(data) {let isArray = Array.isArray(data);let isObject = isPlainObject(data);// 如果是数组/对象,并且不是被冻结/密封/阻止扩展的,我们才处理。if ((isArray || isObject) && Object.isExtensible(data)) {// 防止套娃操作。if (data.hasOwnProperty("__ob__")) {return data;}define(data, "__ob__", true);// 数组:重定向其原型指向 & 对数组每一项进行深度处理。if (isArray) {data.__proto__ = arrayMethods; // Object.setPrototypeOf(data, arrayMethods);observeArray(data);}// 对象:迭代对象中的每一项,对每一项都基于defineProperty进行数据劫持。if (isObject) {let keys = Object.keys(data);let proxy = { ...data };keys.forEach((key) => {defineReactive(data, key, proxy);});}}// console.log(`data-->`, data);return data;
    };// -----做测试。
    let data = {msg: "哈哈",obj: {x: 10,y: {z: [100, 200],},},arr: [1, 2, { n: 1000 }],
    };
    data.data = data;
    observe(data);console.log(`响应式数据:data-->`, data);setTimeout(() => {console.log(`data.arr[1] = "改"`);data.arr[1] = "改"; //视图不更新;
    }, 2000);
    setTimeout(() => {console.log(`data.msg = "改"`);data.msg = "改"; //视图更新;
    }, 1000);
    setTimeout(() => {console.log(`data.arr.push(4, 5, 6)`);data.arr.push(4, 5, 6); //视图更新;
    }, 5000);
    setTimeout(() => {console.log(`data.obj.x = "改了data.obj.x"`);data.obj.x = "改了data.obj.x"; //视图更新;
    }, 10000);// console.log(`data.arr-->`, data.arr);
    

进阶参考

  1. OptionsAPI选项-数据

http://www.ppmy.cn/news/560070.html

相关文章

回收站病毒

就是一个文件夹&#xff0c;文件名是System Volume Information还有一个就是图标以前没有的&#xff0c;就是这段时间才有&#xff0c;不知道是什么问题&#xff1f;求助各位高手~~~ 系统隐藏文件夹(每个盘都有):1.RECYCLER (或者是:回收站图标)2.System Volume Information在…

U盘中病毒,文件消失或不显示

最近非常流行的一个病毒,将电脑或者U盘里的文件全部用快捷方式替换,真实文件被隐藏起来,下面我们就具体了解下此种病毒吧,做好预防与杀毒工作。 一、病毒名称 病毒名称:移动盘同名文件夹病毒;文件夹EXE病毒;同名文件夹EXE病毒 木马名称:Worm.Win32.AutoRun.soq 二、中毒特征 移…

计算机木马不会主动传播什么疾病,研究如何制作自动运行的木马病毒以及如何传播...

我一直对Autorun.inf病毒感兴趣. 这个无敌的家伙使防病毒软件无用,因为它等同于用户单击的病毒或木马. 而且这种传播方式是相对隐蔽的. 今天,我将与我自己讨论如何制作这种U盘病毒. Autorun.inf 此文件位于硬盘分区的根目录中. 只要双击驱动器号,就会自动运行用Autorun.inf编…

开机自动运行记事本病毒的删除

1、打开任务管理器结束wincfgs进程。 2、控制面版-文件夹选项-设置显示系统文件及隐藏文件 3、删除C:\windows\KB20060111.exe&#xff08;也许文件名不同&#xff0c;和记事本一样的蓝色图标&#xff09;。 4、删除C:\windows\system32\wincfgs.exe&#xff08;黄色问号图标的…

信息安全学习笔记(五)------计算机病毒

计算机病毒 病毒概述&#xff1a;病毒是某些人利用计算机软件&#xff0c;硬件所固有的脆弱性&#xff0c;编制的具有特殊功能的程序。其能通过某种途径潜伏在计算机存储介质或程序中&#xff0c;达到某种条件时被激活&#xff0c;同时可以通过修改其他程序的方法感染其他软件&…

怎样查杀U盘病毒

前面一直在测试&#xff0c;在试过几个版本后今天又给杀毒程序进行了下更新&#xff0c;加入了些机房常见所有病毒的查杀对免疫做了优化&#xff0c;免去了复制到跟目下使用的麻烦。 最新版为V2.0 V2.0杀毒程序地址: http://www.rayfile.com/files/1e2b9cc7-00ed-11df-9d46-00…

java kernel32.dll,关于kernel32.sys病毒的问题

今天给一个朋友查看电脑&#xff0c;突然发现kernel32.sys这个启动项&#xff0c;觉得可疑&#xff0c;居然还删不掉&#xff0c;于是搜索了下&#xff0c;把相关的资料整理如下&#xff1a; 1. 症状 (1) 如果系统中安装有WinRAR(一种很好的压缩解压工具&#xff0c;很多电脑上…

病毒分析之伪装360主动防御病毒分析_XiaoBa-20

病毒分析之伪装360主动防御病毒分析_XiaoBa-20 样本概况 说明&#xff1a;此样本应该是之前被抓的黑客XiaoBa的中期作品。&#xff08;见下边截图信息&#xff09; 样本最初于18年1月份发布&#xff0c;我这里于18年2月份捕获&#xff0c;样本并不是太复杂&#xff0c;但影响…