【jsvue】联合gtp仿写一个简单的vue框架,以此深度学习JavaScript

news2024/11/25 14:28:56

用 gtp 学习 Vue 生命周期的原理

lifecycle.js

function Vue(options) {
    // 将选项保存到实例的 $options 属性中
    this.$options = options;

    // 若存在 beforeCreate 钩子函数,则调用之
    if (typeof options.beforeCreate === 'function') {
        options.beforeCreate.call(this);
    }

    // 判断并保存 data 数据对象
    this._data = typeof options.data === 'function' ? options.data() : options.data;

    // 将 data 对象中的属性代理到 Vue 实例上
    this._proxyData();

    // 若存在 created 钩子函数,则调用之
    if (typeof options.created === 'function') {
        options.created.call(this);
    }

    // 执行挂载操作
    this.$mount(options.el);
}

Vue.prototype.$mount = function(el) {
    // 将目标元素保存到实例的 $el 属性中
    this.$el = document.querySelector(el);

    // 若存在 beforeMount 钩子函数,则调用之
    if (typeof this.$options.beforeMount === 'function') {
        this.$options.beforeMount.call(this);
    }

    // 调用 render 方法渲染模板
    this.render();

    // 若存在 mounted 钩子函数,则调用之
    if (typeof this.$options.mounted === 'function') {
        this.$options.mounted.call(this);
    }
};

Vue.prototype._proxyData = function() {
    var self = this;
    // 遍历 data 对象的属性,并将其代理到 Vue 实例上
    Object.keys(this._data).forEach(function(key) {
        Object.defineProperty(self, key, {
            get: function() {
                return self._data[key];
            },
            set: function(newValue) {
                self._data[key] = newValue;
                // 若存在 beforeUpdate 钩子函数,则调用之
                if (typeof self.$options.beforeUpdate === 'function') {
                    self.$options.beforeUpdate.call(self);
                }
                // 重新渲染模板
                self.render();
                // 若存在 updated 钩子函数,则调用之
                if (typeof self.$options.updated === 'function') {
                    self.$options.updated.call(self);
                }
            }
        });
    });
};

Vue.prototype.render = function() {
    // 调用 render 函数生成模板字符串,并更新目标元素的内容
    if (typeof this.$options.render === 'function') {
        this.$el.innerHTML = this.$options.render.call(this);
    }
};

// 使用示例
var app = new Vue({
    el: '#app',  // Vue 实例挂载的目标元素
    data: {      // 数据对象
        message: 'Hello, Vue!'    // 文本数据
    },
    beforeCreate: function() {
        console.log('beforeCreate hook');
    },
    created: function() {
        console.log('created hook');
    },
    beforeMount: function() {
        console.log('beforeMount hook');
    },
    mounted: function() {
        console.log('mounted hook');
    },
    beforeUpdate: function() {
        console.log('beforeUpdate hook');
    },
    updated: function() {
        console.log('updated hook');
    },
    render: function() {
        return '<p>' + this.message + '</p>';
    }
});

注解:
this.$options.beforeMount.call(this);与 this.$options.beforeMount();有什么区别:

  • call(this) 的作用是将当前对象(this)作为参数传递给 beforeMount 方法,使得在 beforeMount 方法内部可以通过 this 访问到当前对象的上下文
  • 直接调用了 beforeMount 方法,没有指定上下文 

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./lifecycle.js"></script>
  </body>
</html>

在浏览器查看渲染结果,并在控制台查看日志输出

另外,我们可以在控制输入 app.message = 'ChatGPT' 来验证数据绑定以及页面更新机制

效果图:

用 gtp 学习 Vue 模板语法和指令的原理

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app"></div>
    <script>
        // 定义 Vue 类
        function Vue(options) {
            // 保存选项为实例的属性
            this.$options = options;
            // 判断传入的 data 是函数还是对象,并保存到 _data 属性上
            this._data = typeof options.data === 'function' ? options.data() : options.data;
            // 调用编译模板的方法
            this._compileTemplate();
        }

        // 原型方法:编译模板
        Vue.prototype._compileTemplate = function () {
            var self = this;
            // 获取模板字符串
            var template = this.$options.template || '';

            // 定义一个函数用于对表达式进行求值
            var evalExpression = function (expression) {
                // 使用 with 关键字将 data 对象的属性添加到作用域中,并求解表达式
                with (self._data) return eval(expression);
            }

            // 将模板中的双括号表达式替换成 data 对应属性的值
            var compiledTemplate = template.replace(/\{\{(.*?)\}\}/g, function (match, expression) {
                var value = evalExpression(expression);
                return value !== undefined ? value : '';
            });

            // 获取目标元素,并将编译后的模板插入其中
            var element = document.querySelector(this.$options.el);
            element.innerHTML = compiledTemplate.trim();

            // 处理带有 v-model 属性的元素,实现数据的双向绑定
            element.querySelectorAll('[v-model]').forEach(function (element) {
                var value = element.getAttribute('v-model');
                element.value = self._data[value];
                element.addEventListener('input', function (event) {
                    self._data[value] = event.target.value;
                });
            });

            // 处理带有 v-text 属性的元素,实现数据的单向绑定
            element.querySelectorAll('[v-text]').forEach(function (element) {
                var value = element.getAttribute('v-text');
                element.textContent = self._data[value];
                // 使用 defineProperty 方法定义 data 对象对应属性的 getter 和 setter
                Object.defineProperty(self._data, value, {
                    get: function () {
                        return this[value]
                    },
                    set: function (newValue) {
                        element.textContent = newValue;
                    }
                });
            });
        };

        // 使用示例
        var app = new Vue({
            el: '#app',  // Vue 实例挂载的目标元素
            data: {      // 数据对象
                message: 'Hello, Vue!',    // 文本数据
                inputValue: 'ChatGPT'      // 输入数据
            },
            template:     // 模板字符串
                `
          <div>
            <p>{{ message }}</p>
            <input v-model="inputValue" type="text">
            <p v-text="inputValue"></p>
         </div>
         `
        });
    </script>
</body>

</html>

效果图:

注解:

  • js中with 语句的作用

with语句的作用是简化代码,使得可以在该作用域内直接访问对象的属性和方法,而无需重复使用对象名字的前缀

var person = {
  name: 'Alice',
  age: 25,
  greet: function() {
    console.log('Hello, ' + this.name + '!');
  }
};

with (person) {
  console.log(name);  // 直接访问属性,输出: Alice
  console.log(age);   // 直接访问属性,输出: 25
  greet();            // 直接调用方法,输出: Hello, Alice!
}
  • template.replace(/\{\{(.*?)\}\}/g, function (match, expression) { ... })

是一个正则表达式替换的方法,用于处理模板中的双花括号表达式 {{expression}},回调函数接收两个参数:

  match:匹配到的整个字符串,即 {{expression}}

  expression:匹配到的表达式,即 expression

 用 gtp 学习 Vue 数据监听和计算属性的原理

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app"></div>
    <script>
        // 定义 Vue 类
        function Vue(options) {
            // 将 data、computed 和 watch 选项保存到实例中
            this._data = options.data;
            this._computed = options.computed;
            this._watch = options.watch;

            // 数据代理
            this._proxyData();
            // 创建计算属性
            this._createComputed();
            // 创建监听器
            this._createWatchers();
        }

        // 数据代理,将 data 中的属性代理到 Vue 实例上,实现直接访问和修改数据
        Vue.prototype._proxyData = function () {
            var self = this;
            Object.keys(this._data).forEach(function (key) {
                Object.defineProperty(self, key, {
                    get: function () {
                        return self._data[key];
                    },
                    set: function (newValue) {
                        self._data[key] = newValue;
                    }
                });
            });
        };

        // 创建计算属性
        Vue.prototype._createComputed = function () {
            var self = this;
            var computed = this._computed || {};

            Object.keys(computed).forEach(function (key) {
                Object.defineProperty(self, key, {
                    get: function () {
                        return computed[key].call(self);
                    }
                });
            });
        };

        // 创建监听器
        Vue.prototype._createWatchers = function () {
            var self = this;
            var watch = this._watch || {};

            Object.keys(watch).forEach(function (key) {
                var callback = watch[key];
                var value = self._data[key];

                Object.defineProperty(self._data, key, {
                    get: function () {
                        return value;
                    },
                    set: function (newValue) {
                        value = newValue;
                        callback.call(self, newValue);
                    }
                });
            });
        };

        // 使用示例
        // 创建一个 Vue 实例
        var app = new Vue({
            // 初始化数据
            data: {
                message: 'Hello, Vue!',
                firstName: 'John',
                lastName: 'Doe'
            },
            // 定义计算属性
            computed: {
                fullName: function () {
                    return this.firstName + ' ' + this.lastName;
                }
            },
            // 定义监听器
            watch: {
                message: function (newValue) {
                    console.log('Message changed:', newValue);
                }
            }
        });

        console.log(app.message);       // 输出: Hello, Vue!
        app.message = 'Hello, Vue.js!'; // 输出: Message changed: Hello, Vue.js!
        console.log(app.message);       // 输出: Hello, Vue.js!
        console.log(app.fullName);      // 输出: John Doe
        app.message = 'New message';    // 输出: Message changed: New message
    </script>
</body>

</html>

效果图:

用 gtp 学习 Vue 事件处理和方法的原理

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app"></div>
    <script>
        // 定义事件总线类
        function EventBus() {
            this._events = {};
        }

        // 事件总线订阅方法,用于注册事件回调函数
        EventBus.prototype.on = function (eventName, callback) {
            if (!this._events[eventName]) {
                this._events[eventName] = [];
            }
            this._events[eventName].push(callback);
        };

        // 事件总线触发方法,用于触发事件并调用相应的回调函数
        EventBus.prototype.emit = function (eventName, payload) {
            if (this._events[eventName]) {
                this._events[eventName].forEach(function (callback) {
                    callback(payload);
                });
            }
        };

        // 定义 Vue 类
        function Vue(options) {
            // 初始化数据
            this._data = typeof options.data === 'function' ? options.data() : options.data;
            // 记录方法
            this._methods = options.methods;
            // 创建事件总线实例
            this._eventBus = new EventBus();

            // 对数据进行代理,使得可以直接通过 this.xxx 访问和修改数据
            this._proxyData();
            // 对方法进行代理,使得可以通过 this.xxx 调用方法
            this._proxyMethods();
        }

        // 数据代理,将 data 中的属性添加到 Vue 实例中,实现直接访问和修改数据
        Vue.prototype._proxyData = function () {
            var self = this;
            Object.keys(this._data).forEach(function (key) {
                Object.defineProperty(self, key, {
                    get: function () {
                        return self._data[key];
                    },
                    set: function (newValue) {
                        self._data[key] = newValue;
                    }
                });
            });
        };

        // 方法代理,将 methods 中的方法添加到 Vue 实例中,实现通过 this.xxx 调用方法
        Vue.prototype._proxyMethods = function () {
            var self = this;
            var methods = this._methods;
            if (methods) {
                Object.keys(methods).forEach(function (key) {
                    self[key] = methods[key].bind(self);
                });
            }
        };

        // 发布事件,触发相应的事件回调函数
        Vue.prototype.$emit = function (eventName, payload) {
            this._eventBus.emit(eventName, payload);
        };

        // 订阅事件,注册事件回调函数
        Vue.prototype.$on = function (eventName, callback) {
            this._eventBus.on(eventName, callback);
        };

        // 创建一个 Vue 实例
        var app = new Vue({
            // 初始化数据
            data: {
                message: 'Hello, Vue!'
            },
            // 定义方法
            methods: {
                greet: function () {
                    this.$emit('greet', this.message);
                },
                updateMessage: function (newMessage) {
                    this.message = newMessage;
                }
            },
        });

        // 注册 greet 事件的回调函数
        app.$on('greet', function (message) {
            console.log('Greet:', message);
        });

        // 调用 greet 方法,触发 greet 事件
        app.greet(); // 输出: Greet: Hello, Vue!

        // 调用 updateMessage 方法,修改 message 的值
        app.updateMessage('Hello, World!');

        // 再次调用 greet 方法,触发 greet 事件,并输出修改后的 message
        app.greet(); // 输出: Greet: Hello, World!
    </script>
</body>

</html>

用 gtp 学习 Vue 插槽(slot)的原理

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app"></div>
    <script>
        // 定义 Vue 构造函数
        function Vue(options) {
            this.$options = options;
            this._data = typeof options.data === 'function' ? options.data() : options.data;
            this._components = options.components || {};

            // 代理 data 属性到 Vue 实例上
            this._proxyData();

            // 编译模板
            this._compileTemplate();

            // 代理组件
            this._proxyComponents();
        }

        // 将 data 对象的属性代理到 Vue 实例上
        Vue.prototype._proxyData = function () {
            var self = this;
            Object.keys(this._data).forEach(function (key) {
                Object.defineProperty(self, key, {
                    get: function () {
                        return self._data[key];
                    },
                    set: function (newValue) {
                        self._data[key] = newValue;
                    }
                });
            });
        };

        // 编译模板
        Vue.prototype._compileTemplate = function () {
            var self = this;
            var el = this.$options.el;
            var template = this.$options.template || '';

            // 使用 evalExpression 函数执行模板中的表达式
            var evalExpression = function (expression) {
                with (self) return eval(expression);
            }

            // 替换模板中的双花括号表达式为对应的数据值
            var compiledTemplate = template.replace(/\{\{(.*?)\}\}/g, function (match, expression) {
                var value = evalExpression(expression);
                return value !== undefined ? value : '';
            });

            // 将编译后的模板插入目标元素中
            var element = el ? document.querySelector(el) : document.createElement('div');
            element.innerHTML = compiledTemplate.trim();
            this.$el = el ? element : element.childNodes[0];
        };

        // 代理组件
        Vue.prototype._proxyComponents = function () {
            var self = this;
            var components = this._components;

            // 遍历组件对象,创建组件实例并进行代理
            Object.keys(components).forEach(function (componentName) {
                var component = new Vue(components[componentName]);

                // 查询所有组件标签,并将子组件的内容替换到对应的插槽中
                self.$el.querySelectorAll(componentName).forEach(function (element) {
                    component.$el.querySelectorAll('slot').forEach(function (slot) {
                        slot.innerHTML = element.innerHTML;
                    });
                    element.innerHTML = component.$el.outerHTML;
                });
            });
        };

        // 使用示例
        var HelloComponent = {
            data: function () {
                return {
                    name: 'John'
                };
            },
            template: `
    <div>
      <h1>{{ name }}</h1>
      <slot></slot>
    </div>
  `
        };

        // 创建 Vue 实例
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello, Vue!'
            },
            components: {
                HelloComponent
            },
            template: `
    <HelloComponent>
      <p>{{ message }}</p>
    </HelloComponent>
  `
        });
    </script>
</body>

</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/970054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt 5.15编译及集成Crypto++ 8.7.0笔记

一、背景 为使用AES加密库&#xff08;AES/CBC加解密&#xff09;&#xff0c;选用Crypto 库&#xff08;官网&#xff09;。   最新Crypto C库依次为&#xff1a;8.8.0版本&#xff08;2023-6-25&#xff09;、8.7.0&#xff08;2022-8-7&#xff09;和8.6.0&#xff08;202…

MySQL数据库——多表查询(4)-实例练习、多表查询总结

目录 练习1 练习2 总结 1.多表关系 2.多表查询 进行案例练习之前&#xff0c;需要先增加一个表格 create table salgrade(grade int,losal int, -- 对应等级的最低薪资hisal int -- 对应等级的最高薪资 ) comment 薪资等级表;insert into salgrade values (1,0,3000)…

【高等数学1800】——一元函数微分学的应用

本文仅用于个人学习记录&#xff0c;使用的教材为汤家凤老师的《高等数学辅导讲义》。本文无任何盈利或者赚取个人声望的目的&#xff0c;如有侵权&#xff0c;请联系删除&#xff01; 文章目录 一、入门练习二、基础练习 一、入门练习 本题需要注意在写凸区间时应该是闭区间。…

华为云云服务器评测|前端开发同学的初体验部署贪吃蛇!

文章目录 前言初配置初始化宝塔面板安装Nginx、上传项目修改nginx配置效果展示 前言 作为一名前端同学&#xff0c;我的技能和日常工作主要集中在用户界面的设计和交互上&#xff0c;与服务器产品相关的经验相对较少。正好看到了咱们华为云开展的评测活动&#xff0c;决定借着…

路径规划 | 图解Lazy Theta*算法(附ROS C++/Python/Matlab仿真)

目录 0 专栏介绍1 Theta*算法局限性2 Lazy Theta*算法原理3 Theta* VS. Lazy Theta*4 仿真实现4.1 ROS C实现4.2 Python实现4.3 Matlab实现 0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详细介绍全局规划(图…

【nerfStudio】2-基于nerfStudio训练第一个NeRF模型

训练第一个NeRF模型 训练和运行查看器 以下内容将训练一个_nerfacto_模型: # 下载一些测试数据: ns-download-data nerfstudio --capture-name=poster # 训练模型 ns-train nerfacto --data data/nerfstudio/poster如果一切正常,应该会看到如下的训练进度: 在终端末尾的…

FPGA GTX aurora 8b/10b编解码 PCIE 板对板视频传输,提供2套工程源码加QT上位机源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、GTX 全网最细解读GTX 基本结构GTX 发送和接收处理流程GTX 的参考时钟GTX 发送接口GTX 接收接口GTX IP核调用和使用 4、设计思路框架视频源选择ADV7611解码芯片配置及采集动态彩条视频数据组包GTX aurora 8b/10b数据…

基于永磁同步发电机的风力发电系统连接到可控的三相整流器(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

机器学习——主成分分析PCA

机器学习——主成分分析PCA 文章目录 前言一、原理1.1. PCA介绍1.2. 算法步骤 二、代码实现2.1. 基于numpy实现2.2. 使用sklearn实现2.3. 观察方差分布2.4. 指定方差百分比求分量数 三、优&#xff0c;缺点3.1. 优点3.2. 缺点 总结 前言 当面对一个特征值极多的数据集时&#…

【核磁共振成像】观共享重建

目录 一、K空间关键孔技术-数据采集二、BRISK技术三、TRICKS技术四、实时成像和滑动窗重建五、心电触发电影(CINE)采集六、分段心脏采集和观共享 一、K空间关键孔技术-数据采集 对于笛卡尔K空间&#xff0c;一个相位编码行有时称为一个K空间观。一般情况下&#xff0c;每帧图像…

电源模块的降额曲线

大家好&#xff0c;这里是大话硬件。 今天想写这篇文章来分享在前段时间了解的一个知识点——电源模块的降额曲线。 为什么要写这个呢&#xff1f;对于专门做电源的同学来说&#xff0c;肯定觉得很简单。但是对于一个非电源行业的人来说&#xff0c;曲线应该如何解读&#xff…

春秋云镜 CVE-2018-1273

春秋云镜 CVE-2018-1273 Spring-data-commons 远程命令执行漏洞 靶标介绍 Spring Data是一个用于简化数据库访问&#xff0c;并支持云服务的开源框架&#xff0c;Spring Data Commons是Spring Data下所有子项目共享的基础框架。Spring Data Commons 在2.0.5及以前版本中&…

leetcode 1859.将句子排序

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;将句子排序 代码&#xff1a; class Solution { public:string sortSentence(string s) {vector<string> record;record.resize(9);string curString;for (auto val : s) {if (isdigit(val)) {record[ val - 0 - …

Linux内核基础知识

1.arm设备的启动过程 x86、Interl windows 启动过程: 电源 ---- >BIOS----->windows内核 --->文件系统(C盘、D盘) ---->应用程序启动嵌入式产品: 树莓派、mini2440、manopi、海思、RK(瑞芯微)等启动过程: 电源-->bootloader (引导操作系统启动) -->linux内…

【人工智能】—_一阶逻辑、量词的推理规则、一般化分离规则、合一、前向_反向链接算法、归结算法

文章目录 量词的推理规则全称量词实例化存在量词实例化 简化到命题逻辑推理Generalized Modus Ponens&#xff08;一般化分离规则&#xff09;举例 合一Forward chaining 前向链接算法示例 Backward chaining algorithm 反向链接算法一般FOL的FC/BC的完整性 归结算法归结推理规…

CEF内核和高级爬虫知识

(转)关于MFC中如何使用CEF内核&#xff08;CEF初解析&#xff09; Python GUI: cefpython3的简单分析和应用 cefpython3&#xff1a;一款强大的Python库 开始大多数抓取尝试可以从几乎一行代码开始&#xff1a; fun main() PulsarContexts.createSession().scrapeOutPages(&q…

PMP中常用英文术语

常用术语&#xff08;五&#xff09; Project 项目 为完成一个唯一的产品或服务的一种一次性努力。 Project Charter 项目许可证 由高级管理部门提供的一个文档&#xff0c;它给项目经理特权把组织的资源应用到项目工作中。 Project Communication Management 项目沟通管理 项目…

3D视觉测量:面对面的对称度 点对(附源码)

文章目录 0. 测试效果1. 基本内容2. 3D视觉测量对称度测量思路3. 代码实现4. 参考文章目录:3D视觉测量目录微信:dhlddxB站: Non-Stop_目标:通过3D视觉方法计算面对面的对称度0. 测试效果 数据说明:此测试点云是通过UG建模,Meshlab降采样得到,数据比较理想,仅作为测试使用…

Blazor前后端框架Known-V1.2.14

V1.2.14 Known是基于C#和Blazor开发的前后端分离快速开发框架&#xff0c;开箱即用&#xff0c;跨平台&#xff0c;一处代码&#xff0c;多处运行。 Gitee&#xff1a; https://gitee.com/known/KnownGithub&#xff1a;https://github.com/known/Known 概述 基于C#和Blazo…

ASIC-WORLD Verilog(16)综合

写在前面 在自己准备写一些简单的verilog教程之前&#xff0c;参考了许多资料----Asic-World网站的这套verilog教程即是其一。这套教程写得极好&#xff0c;奈何没有中文&#xff0c;在下只好斗胆翻译过来&#xff08;加点自己的理解&#xff09;分享给大家。 这是网站原文&…