【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.rhkb.cn/news/121529.html

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

相关文章

类和对象(中)

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; C&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大…

vs2008下的mfc hello world实现

笔者不知道会写这种博文&#xff0c;好久没写mfc程序&#xff0c;hello world都不会创建了。起因是来了个mfc任务&#xff0c;那就得把mfc熟悉起来&#xff0c;先看下实现效果吧 因为是基于2008的&#xff0c;那就按照2008创建吧 文章目录 第一步&#xff1a;文件新建项目第二…

【二等奖方案】大规模金融图数据中异常风险行为模式挖掘赛题「冀科数字」解题思路

第十届CCF大数据与计算智能大赛&#xff08;2022 CCF BDCI&#xff09;已圆满结束&#xff0c;大赛官方竞赛平台DataFountain&#xff08;简称DF平台&#xff09;正在陆续释出各赛题获奖队伍的方案思路&#xff0c;欢迎广大数据科学家交流讨论。 本方案为【大规模金融图数据中…

CS420 课程笔记 P4 - 以16进制形态编辑游戏文件

文章目录 IntroductionFinding save filesStringsUnicodeExample!Value searchHealth searchConclusion Introduction 这节课我们将学习编辑十六进制&#xff0c;主要用于编辑保存文件&#xff0c;但十六进制编辑涉及的技能可以很好地转移到&#xff1a; Save file editingRe…

python数据分析基础—取某列字符的前几个字符

文章目录 前言取某列前几个字符方法一&#xff1a;[x[:7] for x in data["calling_nbr"]]方法二&#xff1a;data[calling_nbr].str[:7] 前言 在进行数据分析时&#xff0c;有时候我们需要提取单列的前几个字符串进行分析。本文主要讲述针对这种情况处理方法。 取某…

Keil Flash的下载算法

更进一步的了解Keil Flash的下载算法 前面提到了通用算法的选择&#xff0c;那么问题来了&#xff0c;这个算法文件如何来的呢&#xff1f;如果你所用的MCU不是默认支持的品牌&#xff0c;如何编写属于自己的算法呢&#xff1f; 工具/原料 Keil uVision ULINK2仿真器 方法/…

无涯教程-JavaScript - DAYS函数

描述 DAYS函数返回两个日期之间的天数。 语法 DAYS (end_date, start_date)争论 Argument描述Required/OptionalEnd_dateStart_date and End_date are the two dates between which you want to know the number of days.RequiredStart_dateStart_date and End_date are th…

推荐6款普通人搞副业做自媒体AI工具

hi&#xff0c;同学们&#xff0c;我是赤辰&#xff0c;本期是赤辰第5篇AI工具类教程&#xff0c;文章底部准备了粉丝福利&#xff0c;看完可以领取&#xff01;身边越来越多的小伙伴靠自媒体实现财富自由了&#xff01;因此&#xff0c;推荐大家在工作之余或空闲时间从事自媒体…

Java8新特性 - Lambda表达式

目录 一、Lambda表达式 1.1、为什么使用Lambda表达式&#xff1f; 1.2、Lambda的标准格式 Lambda的标准格式 无参无返回值的Lambda 有参有返回值的Lambda 1.3、Lambda的实现原理 1.4、Lambda省略模式 1.5、Lambda表达式的前提条件 1.6、Lambda与匿名内部类对比 1.7、…

SpringMvc框架入门使用(详细教程)

目录 ​编辑 1.SpringMVC框架是什么&#xff1f; 2.SpringMVC工作流程 3.SpringMVC的入门 3.1 pom.xml 3.2spring-mvc.xml 3.3web.xml 3.4 建立一个web的方法 4.5 建立一个首页 4.6效果展示 4.图片处理 1.SpringMVC框架是什么&#xff1f; Spring MVC是一个基…

嵌入式Linux开发实操(十六):Linux驱动模型driver model

嵌入式linux下驱动模型: 1、驱动的绑定 驱动程序绑定driver binding 驱动程序绑定是将设备device与可以控制它的设备驱动程序driver相关联的过程。总线驱动程序bus driver通常会处理,因为有特定于总线bus的结构来表示设备device和驱动程序driver。使用通用的设备device和设…

基于 Flink CDC 构建 MySQL 和 Postgres 的 Streaming ETL

官方网址&#xff1a;https://ververica.github.io/flink-cdc-connectors/release-2.3/content/%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B/mysql-postgres-tutorial-zh.html官方教程有些坑&#xff0c;经过自己实测&#xff0c;记录个笔记。 服务器环境&#xff1a; VM虚拟机&am…

潜艇来袭(Qt官方案例-2维动画游戏)

一、游戏介绍 1 开始界面 启动程序&#xff0c;进入开始界面。 2 开始新游戏 点击菜单&#xff1a;File》New Game &#xff08;或者CtrlN&#xff09;进入新游戏。 开始新游戏之后&#xff0c;会有一个海底的潜艇&#xff0c;和水面舰艇对战。 计算机&#xff1a;自动控制…

STM32f103入门(4)对射式红外传感器计次(外部中断)

中断:在主程序运行过程中&#xff0c;出现了特定的中断触发条件 (中断源)&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序处理完成后又返回原来被暂停的位置继续运行中断优先级:当有多个中断源同时申请中断时&#xff0c;CPU会根据中断源的轻重缓急进…

深度学习推荐系统(四)WideDeep模型及其在Criteo数据集上的应用

深度学习推荐系统(四)Wide&Deep模型及其在Criteo数据集上的应用 在2016年&#xff0c; 随着微软的Deep Crossing&#xff0c; 谷歌的Wide&Deep以及FNN、PNN等一大批优秀的深度学习模型被提出&#xff0c; 推荐系统全面进入了深度学习时代&#xff0c; 时至今日&#x…

聚焦磷酸铁锂产线革新,宏工科技一站式解决方案

兼顾了低成本与安全性两大属性&#xff0c;磷酸铁锂市场在全球范围内持续升温&#xff0c;并有望保持较高的景气度。巨大的需求空间之下&#xff0c;行业对于锂电装备企业的自动化与智能化水平、整线交付能力、产品效率与稳定性等均提出了新的要求。 以宏工科技股份有限公司&a…

C#通过ModbusTcp协议读写西门子PLC中的浮点数

一、Modbus TCP通信概述 MODBUS/TCP是简单的、中立厂商的用于管理和控制自动化设备的MODBUS系列通讯协议的派生产品&#xff0c;显而易见&#xff0c;它覆盖了使用TCP/IP协议的“Intranet”和“Internet”环境中MODBUS报文的用途。协议的最通用用途是为诸如PLC&#xff0c;I/…

LiveGBS流媒体平台GB/T28181功能-支持数据库切换为高斯数据库信创瀚高数据信创数据库

LiveGBS流媒体平台GB/T28181功能-支持数据库切换为高斯数据库信创瀚高数据信创数据库 1、如何配置切换高斯数据库&#xff1f;2、如何配置切换信创瀚高数据库&#xff1f;3、搭建GB28181视频直播平台 1、如何配置切换高斯数据库&#xff1f; livecms.ini -> [db]下面添加配…

华为Mate60低调发布,你所不知道的高调真相?

华为Mate60 pro 这两天的劲爆新闻想必各位早已知晓&#xff0c;那就是华为Mate60真的来了&#xff01;&#xff01;&#xff01;并且此款手机搭载了最新国产麒麟9000s芯片&#xff0c;该芯片重新定义了手机性能的巅峰。不仅在Geekbench测试中表现出色&#xff0c;还在实际应用…