当前位置: 首页 > news >正文

vue核心原理实现

vue示例

通过一个小案例, 对比vue开发和原生开发的区别

  1. vue的核心就是数据响应式, 数据改变视图跟随改变
  2. 通过数据驱动视图, 我们就不用直接操作DOM元素了, 这就是vue开发与原生开发的区别
<!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>Document</title><link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" /><link rel="stylesheet" href="./css/index.css" /></head><body><div class="container"><h1 class="head">{{title}}</h1><div class="list"><divv-for="item in goods"class="list-item":class="{active: item.choose>0}"><div class="title">{{item.name}}</div><div class="controls"><i @click="item.choose--" class="iconfont i-jianhao"></i><span>{{item.choose}}</span><i@click="item.choose++"class="iconfont i-jiajianzujianjiahao"></i></div></div></div><div class="footer"><divclass="car":class="{active: count > 0}"><i class="iconfont i-gouwuchefill"></i><span class="badge">{{count}}</span></div></div></div><script src="./js/data.js"></script><script src="./js/vue.js"></script><script src="./js/index.js"></script></body>
</html>
var goods = [{name: 'iPhone 12',choose: 0,},{name: '荣耀X30',choose: 1,},{name: 'Redmi Note 11',choose: 3,},{name: 'OPPO K9x',choose: 0,},{name: '华为Nova10pro',choose: 1,},
];
var vm = new Vue({// 配置对象el: '.container',data: {// 界面数据title: '淘东手机',goods: goods,},// 计算属性computed: {count: function () {var sum = 0;for (var i = 0; i < this.goods.length; i++) {sum += this.goods[i].choose;}return sum;},},
});

vue原理

准备基础代码

.card {width: 300px;border: 2px solid rgb(74, 125, 142);border-radius: 10px;font-size: 2em;padding: 0 20px;margin: 0 auto;background: lightblue;color: #333;
}
<!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>Document</title><link rel="stylesheet" href="./index.css" />
</head><body><div class="card"><p id="firstName"></p><p id="lastName"></p><p id="age"></p></div>// <input type="text" oninput="user.name = this.value" />// <input type="date" onchange="user.birth = this.value" /><script src="./index.js"></script>
</body></html>
var user = {name: '袁进',birth: '2002-5-7',
};// 显示姓氏
function showFirstName() {document.querySelector('#firstName').textContent = '姓:' + user.name[0];
}// 显示名字
function showLastName() {document.querySelector('#lastName').textContent = '名:' + user.name.slice(1);
}// 显示年龄
function showAge() {var birthday = new Date(user.birth);var today = new Date();today.setHours(0), today.setMinutes(0), today.setMilliseconds(0);thisYearBirthday = new Date(today.getFullYear(),birthday.getMonth(),birthday.getDate());var age = today.getFullYear() - birthday.getFullYear();if (today.getTime() < thisYearBirthday.getTime()) {age--;}document.querySelector('#age').textContent = '年龄:' + age;
}showFirstName()
showLastName()
showAge()

改造一下程序, 初步实现 "数据驱动视图"

var user = {name: '袁进',birth: '2002-5-7',
};// 显示姓氏
function showFirstName() {document.querySelector('#firstName').textContent = '姓:' + user.name[0];
}// 显示名字
function showLastName() {document.querySelector('#lastName').textContent = '名:' + user.name.slice(1);
}// 显示年龄
function showAge() {var birthday = new Date(user.birth);var today = new Date();today.setHours(0), today.setMinutes(0), today.setMilliseconds(0);thisYearBirthday = new Date(today.getFullYear(),birthday.getMonth(),birthday.getDate());var age = today.getFullYear() - birthday.getFullYear();if (today.getTime() < thisYearBirthday.getTime()) {age--;}document.querySelector('#age').textContent = '年龄:' + age;
}showFirstName()
showLastName()
showAge()/*** 当我们改变数据时, 如何让视图更新呢?* --重新调用一下方法呗! 这不很简单嘛 */
user.name = '张三彭'
showFirstName()
showLastName()user.birth = '1999-1-1'
showAge()/*** 可以实现自动调用方法吗? * 当我改变了数据, 就自动调用方法更新视图.岂不美哉?* --我来试试吧*/
user.name = '张三彭'
// 如何自动调用依赖该属性的函数?
// showFirstName()
// showLastName()/*** 思路分析* 1.如何感知属性的读取和设置呢? -- 属性访问器* 2.自动调用依赖属性的方法*/
let internalName = user.name;
Object.defineProperty(user, 'name', {get: function () {console.log('有人在读取 name 属性');return internalName;},set: function (val) {internalName = valconsole.log('有人修改 name 属性, 值为' + val);showFirstName()showLastName()}
})
user.name = '李四康'

  1. 现在, 无论是通过编码还是通过控制台, 只要修改了user对象的name属性, 就可以自动调用该属性的方法, 从而自动更新视图

上面的代码还只是玩具, 如果需要通用, 就要封装

/*** 观察对象的所有属性*/
// 问题1: 如何调用依赖该属性的函数???
// --在get函数中依赖收集
// --在set函数中派发更新
function observe(obj) {for (const key in obj) {let internalValue = obj[key]let funcs = [];Object.defineProperty(obj, key, {get: function () {// 依赖收集:  记录是哪些函数在用我if (window.__func && !funcs.includes(window.__func)) {funcs.push(window.__func);}return internalValue},set: function (val) {internalValue = val// 派发更新: 运行依赖我的函数for (let index = 0; index < funcs.length; index++) {funcs[index]()}}})}
}// 问题2: 依赖怎么收集呢?
// --封装一个代理方法, 方法执行前记录方法
// --方法不要直接调用, 使用代理方法间接调用
// autorun <- showFristName
function autorun(fn) {window.__func = fnfn()window.__func = null
}
var user = {name: '袁进',birth: '2002-5-7',
};// 显示姓氏
function showFirstName() {document.querySelector('#firstName').textContent = '姓:' + user.name[0];
}// 显示名字
function showLastName() {document.querySelector('#lastName').textContent = '名:' + user.name.slice(1);
}// 显示年龄
function showAge() {var birthday = new Date(user.birth);var today = new Date();today.setHours(0), today.setMinutes(0), today.setMilliseconds(0);thisYearBirthday = new Date(today.getFullYear(),birthday.getMonth(),birthday.getDate());var age = today.getFullYear() - birthday.getFullYear();if (today.getTime() < thisYearBirthday.getTime()) {age--;}document.querySelector('#age').textContent = '年龄:' + age;
}/*** 封装代码*/
observe(user) // 观察对象autorun(showFirstName)
autorun(showLastName)
autorun(showAge)
<!DOCTYPE html>
<html lang="en"><head>... ... 
</head><body><div class="card"><p id="firstName"></p><p id="lastName"></p><p id="age"></p></div><input type="text" oninput="user.name = this.value" /><input type="date" onchange="user.birth = this.value" /><script src="./iuv.js"></script><script src="./index.js"></script>
</body></html>

  1. 整个代码的健壮性还是不够的, 但是代码的思想跟vue源码是一致的
  2. 数据响应式的本质是数据变化后自动调用依赖数据的方法
http://www.dtcms.com/a/402973.html

相关文章:

  • 在docker中容器使用iptables限制IP访问端口
  • iOS 26 耗电检测实战攻略,如何测电量掉速、定位高耗能模块与优化策略(适用于 uni-app 原生 App)
  • uniapp+<script setup lang=“ts“>解析后端返回的图片流并将二维码展示在页面中
  • 1- 十大排序算法(选择排序、冒泡排序、插入排序)
  • uniapp x 鸿蒙开发之调试证书签名配置
  • RabbitMQ-消息堆积
  • uniapp x鸿蒙开发之运行到鸿蒙模拟器
  • wordpress建站 外贸适合做装饰公司的名字
  • Web3实操:2025年DePIN 挂机项目要点分享
  • 公司做网站费用wordpress alchem
  • 内存对齐与变量/结构体分析
  • 常见开发语言在 Windows 上的默认编码格式
  • 卫朋:AI硬件产品怎么做?——雷达模块选型实操
  • 从另一个视角看Transformer:注意力机制就是可微分的k-NN算法
  • [优选算法专题三.二分查找——NO.21山脉数组的峰顶索引]
  • 湖南营销型网站建设推广如何更改网站标题
  • 云原生网络基础设施的核心组件Envoy
  • KubeSphere 社区版即将发布:开启云原生新篇章
  • K8s学习笔记(五) Velero结合minnio业务数据备份与恢复
  • 23种设计模式——组合模式(Composite Pattern)
  • 培训机构网站开发汉中杨海明
  • 2- 十大排序算法(希尔排序、计数排序、桶排序)
  • 哈尔滨服务器托管优选-青蛙云
  • 【MySQL】JDBC
  • sogoupinyin输入法,LINUX版输入中文不显示中文
  • 自动化运维工具 Ansible:集中化管理服务器完全指南
  • 电影网站的建设目标做网站的公司简称什么行业
  • 【ThreeJs】【HTML载入】Three.js 中的 CSS2DRenderer 与 CSS3DRenderer 全面解析
  • (50)elasticsearch服务部署-有状态负载(华为云平台CCE)
  • 【时序预测-5】FFT、STL、ARIMA频域特征和时序分解