|
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.js
- import { 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 文件暴露出一个方法,该方法主要是处理初始化的数据:- // vue/init.js
- import 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
- };
复制代码 以上代码,我们通过对中的数据进行拦截,详情如下:- // vue/proxy.js
- function 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;
复制代码 我们还调用了方法进行事件订阅,详细如下:- // vue/observe.js
- import 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
- import 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;
复制代码 以上代码,我们分别对数组和对象执行不同的操作,我们先来看对象的操作:
在构造函数中我们新增了一个方法,该方法获取到了所有的值,然后调用了进行处理。
[code]// 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(`
来源:https://www.jb51.net/article/276273.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|