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

用 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 和 setterObject.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);  // 直接访问属性,输出: Aliceconsole.log(age);   // 直接访问属性,输出: 25greet();            // 直接调用方法,输出: 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 Doeapp.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 事件,并输出修改后的 messageapp.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.mzph.cn/news/66879.shtml

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

相关文章

ChatGPT Prompting开发实战(四)

一、chaining prompts应用解析及输出文本的设定 由于输入和输出都是字符串形式的自然语言&#xff0c;为了方便输入和输出信息与系统设定使用的JSON格式之间进行转换&#xff0c;接下来定义从输入字符串转为JSON list的方法&#xff1a; 定义从JSON list转为输出字符串的方法&…

[华为云云服务器评测] Unbutnu添加SSH Key、编译启动Springboot项目

系列文章目录 第一章 [linux实战] 华为云耀云服务器L实例 Java、node环境配置 第二章 [linux实战] Unbutnu添加SSH Key、启动Springboot项目 文章目录 系列文章目录前言一、任务拆解二、配置git,添加SSH Key2.1、登录远程主机2.2、配置git用户名和邮箱2.3、生成SSH key2.4、查…

第 361 场 LeetCode 周赛题解

A 统计对称整数的数目 枚举 x x x class Solution { public:int countSymmetricIntegers(int low, int high) {int res 0;for (int i low; i < high; i) {string s to_string(i);if (s.size() & 1)continue;int s1 0, s2 0;for (int k 0; k < s.size(); k)if …

钡铼R40边缘计算网关与华为云合作,促进物联网传感器数据共享与应用

场景说明 微型气象是不可预测的&#xff0c;基本上不能通过人工手段来分析其变化&#xff0c;因此必须运用新技术&#xff0c;对气象进行实时监测&#xff0c;以便采取相应的措施来避免或解决事故的发生。而常规气象环境数据采集容易造成数据损失、人力成本高、数据安全性差、…

升级iOS17后iPhone无法连接App Store怎么办?

最近很多用户反馈&#xff0c;升级最新iOS 17系统后打开App Store提示"无法连接"&#xff0c;无法正常打开下载APP。 为什么升级后无法连接到App Store&#xff1f;可能是以下问题导致&#xff1a; 1.网络问题导致App Store无法正常打开 2.网络设置问题 3.App Sto…

项目介绍:《Online ChatRoom》网页聊天室 — Spring Boot、MyBatis、MySQL和WebSocket的奇妙融合

在当今数字化社会&#xff0c;即时通讯已成为人们生活中不可或缺的一部分。为了满足这一需求&#xff0c;我开发了一个名为"WeTalk"的聊天室项目&#xff0c;该项目基于Spring Boot、MyBatis、MySQL和WebSocket技术&#xff0c;为用户提供了一个实时交流的平台。在本…

渗透测试漏洞原理之---【任意文件包含漏洞】

文章目录 1、文件包含概述1.1 文件包含语句1.1.1、相关配置 1.2、动态包含1.2.1、示例代码1.2.2、本地文件包含1.2.3、远程文件包含 1.3、漏洞原理1.3.1、特点 2、文件包含攻防2.1、利用方法2.1.1、包含图片木马2.1.2、读取敏感文件2.1.3、读取PHP文件源码2.1.4、执行PHP命令2.…

MongoDb-01——Mac上安装MongoDb以及相关的简单命令

MongoDb-01——Mac上安装MongoDb以及相关的简单命令 1. 下载、安装1.1 官网下载1.2 关于安装MongoDB1.2.1 官方安装文档1.2.2 Mac安装详细步骤&#xff08;使用brew&#xff09; 2. 启动MongoDB2.1 官方说明2.2 作为macOS服务运行的相关命令2.3 访问 3. 链接并使用mongodb3.1 链…

docker笔记3 Docker常规安装

1.安装tomcat docker hub上面查找tomcat镜像 docker search tomcat 从docker hub上拉取tomcat镜像到本地 docker pull tomcat docker images查看是否有拉取到的tomcat 使用tomcat镜像创建容器实例(也叫运行镜像) docker run -it -p 8080:8080 tomcat -p 小写&#xff0c;主…

零撸大肉,赛博尔Seppol游戏,无限制闯关打碎片,装备,直接变现项目。

2023年7月10日&#xff0c;在上海外滩酒店—— 由来自硅谷、华尔街的技术先锋&#xff0c;与中国科技翘楚阿里、腾讯的骨干团队联手呈现&#xff0c;区块链元宇宙游戏塞波尔 Seppol于上海精彩亮相路演。 1&#xff0c;栖息之地&#xff0c;宠物可放入栖息之地进行挖矿&#xf…

【STM32】学习笔记(OLED)

调试方式 OLED简介 硬件电路 驱动函数 OLED.H #ifndef __OLED_H #define __OLED_Hvoid OLED_Init(void); void OLED_Clear(void); void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char); void OLED_ShowString(uint8_t Line, uint8_t Column, char *String); void OL…

地质灾害监测方案(地质灾害监测原理与方法)

我国坡地较多,地质灾害时有发生,给人民生命财产安全和经济建设造成严重威胁。采用工业物联网技术进行地质灾害监测,可以实现对山体移动、边坡变形等地质灾害的预警和实时监测,保护人民生命财产安全。现提出如下地质灾害监测方案: 1. 监测场景:针对易发地质灾害的区域,如矿山边坡…

ReactNative 井字游戏 实战

效果展示 需要的插件准备 此实战项目需要用到两个插件。 react-native-snackbar 底部信息提示组件。 react-native-vector-icons 图标组件。 安装组件&#xff1a; npm i react-native-snackbar npm i react-native-vector-icons npm i types/react-native-vector-icons /…

java企业工程项目管理系统源码(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff…

Opencv手工选择图片区域去水印

QT 插件化图像算法研究平台的功能在持续完善&#xff0c;补充了一个人工选择图片区域的功能。 其中&#xff0c;图片选择功能主要代码如下&#xff1a; QRect GLImageWidget::getSeleted() {QRect ajust(0,0,0,0);if(image.isNull() || !hasSelection)return ajust;double w1…

Springboot 接口方式硬通知实现ConfigurationProperties 、@Value 动态刷新

前言 看到这个文章标题&#xff0c;也许有的看官就觉得很多余&#xff0c; 因为Nacos 可以设置 NacosValue(value "${XXX}",autoRefreshed true) 实现动态刷新&#xff1b; 又因为cloud config的RefreshScope 实现动态刷新&#xff1b; 还有阿波罗...等 这…

【python爬虫】13.吃什么不会胖(爬虫实操练习)

文章目录 前言项目实操明确目标分析过程代码实现 前言 吃什么不会胖——这是我前段时间在健身时比较关注的话题。 相信很多人&#xff0c;哪怕不健身&#xff0c;也会和我一样注重饮食的健康&#xff0c;在乎自己每天摄入的食物热量。 不过&#xff0c;生活中应该很少有人会…

景联文科技:高质量AI数据标注助力大语言模型训练,推动人工智能落地应用

大语言模型在各类LLM新技术的融会贯通下&#xff0c;不断加速Instruction-tuning、RLHF、思维链等新技术在大语言模型中的深度应用&#xff0c;人工智能技术以惊人的速度不断进化。 大语言模型&#xff08;LLM&#xff09;是一种基于深度学习技术和海量文本数据&#xff0c;它们…

Leetcode:349. 两个数组的交集【题解超详细】

题目 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 难度&#xff1a;简单 题目链接&#xff1a;349.两个数组的交集 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,…

【08期】ArrayList常见面试题

简介 ArrayList是我们开发中非常常用的数据存储容器之一&#xff0c;其底层是数组实现的&#xff0c;我们可以在集合中存储任意类型的数据&#xff0c;ArrayList是线程不安全的&#xff0c;非常适合用于对元素进行查找&#xff0c;效率非常高。 线程安全性 对ArrayList的操作…