首页前端开发VUEVue2 中的数据劫持简写示例

Vue2 中的数据劫持简写示例

时间2024-02-11 06:15:02发布访客分类VUE浏览820
导读:收集整理的这篇文章主要介绍了Vue2 中的数据劫持简写示例,觉得挺不错的,现在分享给大家,也给大家做个参考。 目录package.json 相关依赖Webpack.config.js 配...
收集整理的这篇文章主要介绍了Vue2 中的数据劫持简写示例,觉得挺不错的,现在分享给大家,也给大家做个参考。
目录
  • package.json 相关依赖
  • Webpack.config.js 配置文件
  • public/index.html 文件内容
  • 全部文件目录结构
  • 实例一个模拟的 Vue 应用
    • vue/index.js 文件主要是负责初始化内容
    • initState方法
    • 核心文件vue/observer.js
    • vue/observer.js文件对数组进行处理

package.JSON 相关依赖

我们今天要编写的项目通过需要使用 Webpack 进行编译,package.json 相关依赖如下:

{
  "scripts": {
    "dev": "webpack-dev-server",    "build:": "webpack"  }
,  "devDePEndencies": {
    "htML-webpack-plugin": "^4.5.2",    "webpack": "^4.46.0",    "webpack-cli": "^3.3.12",    "webpack-dev-server": "^3.11.3"  }
}
    

Webpack.config.js 配置文件

const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  entry: "./src/index.js",  output: {
    filename: "bundle.js",    path: path.resolve(__dirname, "dist")  }
,  devtool: "source-map",  resolve: {
    // 表示解析模块引入的时候先从当前文件夹寻找模块,再去 node_modules 找模块    modules: [      path.resolve(__dirname, ""),       path.resolve(__dirname, "node_modules")    ]  }
,  plugins: [    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "public/index.html")    }
)  ]}
    ;
    

public/index.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>
    /title>
      /head>
      body>
        div id="app">
    /div>
      /body>
    /html>
    

全部文件目录结构

好了,接下来我们就开始发车!

实例一个模拟的 Vue 应用

首先,我们需要编写我们的入口文件 index.js,该文件很普通主要就是实例一个模拟的 Vue 应用:

// index.js// 我们在 webpack.config.js 中进行了配置,所以这里优先在当前目录下寻找 vue 文件,也就是我们的 vue/index.js 文件import Vue From "vue";
 let vm = new Vue({
  el: "#app",  data() {
    return {
      title: "学生列表",      classNum: 1,      teacher: ["张三", "李四"],      info: {
        a: {
          b: 1        }
      }
,      students: [        {
          id: 1,          name: "小红"        }
,        {
          id: 2,          name: "小明"        }
      ]    }
    ;
  }
}
    );
    console.LOG(vm);
    

vue/index.js 文件主要是负责初始化内容

// src/sindex.jsimport {
 initstate }
     from "./init";
function Vue(options) {
      this._init(options);
}
Vue.PRototype._init = function (options) {
      // this 指向当前实例对象  VAR vm = this;
      // 我们把 new Vue() 时候传递的数据统称为 options  // 并且挂载到 Vue 的实例对象上  vm.$options = options;
      // 调用 initState 初始化 data 数据  initState(vm);
}
    ;
    export default Vue;
    

initState方法

vue/init.js 文件暴露出一个initState方法,该方法主要是处理初始化的数据:

// vue/init.jsimport ProxyData from "./proxy";
import observer from "./observe"function initState(vm) {
      var options = vm.$options;
  // 如果 options 中存在 data 属性,我们才会继续处理  if (options.data) {
        initData(vm);
  }
}
function initData(vm) {
      var data = vm.$options.data;
  // 把 data 数据单独保存到 Vue 的实例化对象上,方便我们获取  // 如果 data 是一个函数,我们需要执行返回得到返回的对象  data = vm._data = typeof data === "function" ? data.call(vm) : data || {
}
    ;
  // 遍历 data 对象,通过 proxyData 对数据进行拦截  for (const key in data) {
        // 传入的参数分别是:当前实例、key值(也就是 vm._data)、data 中的 key 值(例如 vm._data.title)    proxyData(vm, "_data", key);
  }
  // 调用观察者模式  observer(vm._data)}
export {
   initState}
    ;
    

以上代码,我们通过proxyDatadata中的数据进行拦截,详情如下:

// vue/proxy.jsfunction proxyData(vm, target, key) {
  // 当访问 vm.title 的时候转换为 vm._data.title  //(请记住这句话!!!)  Object.defineProperty(vm, key, {
    get: function () {
          return vm[target][key];
    }
,    set: function (newVal) {
          vm[target][key] = newVal;
    }
  }
    );
}
    export default proxyData;
    

我们还调用了observer方法进行事件订阅,详细如下:

// vue/observe.jsimport Observer from "./observer"function observe(data) {
  // 判断只处理对象,如果不是对象直接返回  if (typeof data !== "object" || data === null) {
        return false;
  }
  // 观察数据  return new Observer(data)}
    export default observe;
    

核心文件vue/observer.js

接下来就是我们的核心文件vue/observer.js,该文件主要负责对数据类型进行判断,如果是数组就需要单独处理数组,这个我们后面再说:

// vue/observer.jsimport defineReactiveData from "./reactive";
import {
 arrMethods }
     from "./array";
    import observeArr from "./observeArr";
// 这个方法会在多个地方调用,请记住这个方法以它的作用function Observer(data) {
  // 如果 data 是一个数组,那面需要单独处理  if (Array.isArray(data)) {
        // 给数组新增一层原型    data._proto__ = arrMethods;
    // 循环数组的每一项,然后让每一项都调用 Observer 方法进行订阅    observeArr(data)  }
 else {
        // 处理对象    this.walk(data);
  }
}
Observer.prototype.walk = function (data) {
      // 获取到 data 全部的 key  // 也就是我们定义的 ['title', 'classNum', 'teacher', 'info', 'students']  let keys = Object.keys(data);
      for (var i = 0;
     i  keys.length;
 i++) {
        let key = keys[i];
        let value = data[key];
        // 拦截 data 数据    // 分别传入参数为:vm._data、data 中的 key、data 中 key 对应的 value    defineReactiveData(data, key, value);
  }
}
    ;
    export default Observer;
    

以上代码,我们分别对数组和对象执行不同的操作,我们先来看对象的操作:

Observer构造函数中我们新增了一个walk方法,该方法获取到了所有的key值,然后调用了defineReactiveData进行处理。

// vue/reactive.jsimport observe from "./observe";
function defineReactiveData(data, key, value) {
      // 例如 info.a 还是个对象,那么就递归观察  observe(value);
  // 这里的 data 是 vm._data,所以这里拦截的也是 vm._data  Object.defineProperty(data, key, {
    get() {
      console.log(`⤴️ 响应式获取:data.${
key}
    ,`, value);
          return value;
    }
,    set(newVal) {
          console.log(`

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: Vue2 中的数据劫持简写示例
本文地址: https://pptw.com/jishu/609426.html
命令行CLI一键生成各种烦人的lint配置实例 vue项目登录成功拿到令牌跳转失败401无登录信息的解决

游客 回复需填写必要信息