(精华)2020年7月19日 vue 手写vue底层源码
发布日期:2021-06-29 15:08:03 浏览次数:3 分类:技术文章

本文共 5597 字,大约阅读时间需要 18 分钟。

MYvue.js 主要作用监听属性变化

class MYvue {
constructor(options) {
this.$options = options; this.$data = options.data; //数据劫持 this.observe(this.$data); this.$el = options.el; //包含Watcher创建 new Complie(options.el, this) } //数据劫持 observe(data) {
if (!data || typeof data != 'object') {
return; } Object.keys(data).forEach((key) => {
//让数据可观测 //this.$data.test 改变 this.defineReactive(data, key, data[key]); //this.test 代理改变 this.proxyData(key); }) } //让数据可观测 defineReactive(obj, key, value) {
var dept = new Dep(); //value值为对象递归遍历 this.observe(value); Object.defineProperty(obj, key, {
get() {
//属性被读取了,将来需要添加订阅 console.log('我被读取了'); //将Dep.target(当前的watcher对象存入Dep的deps) Dep.target && dept.addDep(Dep.target) return value; }, set(newVal) {
if (newVal == value) {
return; } value = newVal; console.log(key + '属性更行了,他更新的值是' + newVal); //如果我被改变, 我将来会在这里通知的 dept.notify(); //变化的数据,让watcher的update方法执行 }, enumerable: true, configurable: true }) } //代理data中的属性到vue实例上 proxyData(key) {
Object.defineProperty(this, key, {
get() {
return this.$data[key] }, set(newVal) {
this.$data[key] = newVal; } }) }}//Dep 用来管理wather,管理者的角色class Dep {
constructor() {
//存放所有的依赖(watcher),一个watcher对应一个属性 this.deps = []; } //收集订阅者 addDep(sub) {
this.deps.push(sub); } //通知订阅更新 notify() {
this.deps.forEach((sub) => {
//你要更新了 sub.update() //update是watchr里面的一个函数 }) }}//监听器对象class Watcher {
constructor(vm, key, cb) {
// vm :Vue实例化对象 // key: 需要监听的属性 // cb: 是Watccher绑定的更新函数 this.vm = vm; this.key = key; this.cb = cb; Dep.target = this;//this指Watcher本身 this.vm[key] // 触发getter ,添加依赖 Dep.target = null; } update() {
console.log('你的属性要更新了'); this.cb.call(this.vm, this.vm[this.key]); }}

Complie.js 把属性变化重新渲染html

class Complie {
constructor(el, vm) {
//遍历节点 this.$el = document.querySelector(el); this.$vm = vm; //编译 if (this.$el) {
//转换内容为片段fragment this.$fragment = this.node2Fragment(this.$el); //执行编译 this.replaceTemplate(this.$fragment) //将编译完的html结果追加到$el this.$el.appendChild(this.$fragment); } } node2Fragment(el) {
// createDocumentFragment 用来创建虚拟dom节点 var frag = document.createDocumentFragment(); let child; //讲el中所有的元素搬家到frag while (el.firstChild && (child = el.firstChild)) {
frag.appendChild(child); } return frag; } //对el立面的内容进行替换 // 对el里面的内容进行替换 replaceTemplate(frag) {
// console.log('frag.childNodes',frag.childNodes); var childNodes = Array.from(frag.childNodes); if (childNodes.length == 0) return; childNodes.forEach(node => {
let txt = node.textContent; let reg = /\{\{(.*?)\}\}/g; // 正则匹配{
{}} // 只读属性 Node.nodeType 表示的是该节点的类型 // nodeType 属性可用来区分不同类型的节点,比如 元素, 文本 和 注释。 // 即是文本节点又有大括号的情况{
{}} if (node.nodeType === 3 && reg.test(txt)) {
// console.log(RegExp.$1); // 匹配到的第一个分组 如: a.b, c let arr = RegExp.$1.split('.'); let valTest = this.$vm; arr.forEach(key => {
valTest = valTest[key]; // 如this.a.b }); // 用trim方法去除一下首尾空格 node.textContent = txt.replace(reg, valTest).trim(); // 监听变化,第二步加的 // 给Watcher再添加两个参数,用来取新的值(newVal)给回调函数传参 new Watcher(this.$vm, RegExp.$1, newVal => {
//这里是有属性改变的时候会更新数据 node.textContent = txt.replace(reg, newVal).trim(); }); } // v-modle数据的双向绑定 if (node.nodeType === 1) {
// 元素节点 let nodeAttr = Array.from(node.attributes); // 获取dom上的所有属性,是个类数组 nodeAttr.length > 0 && nodeAttr.forEach(attr => {
let name = attr.name; // v-model type let exp = attr.value; // c text if (name.includes('v-')) {
node.value = this.$vm[exp]; // this.c 为 2 } // oninput .onclick node.addEventListener('input', e => {
let newVal = e.target.value; // 相当于给this.c赋了一个新值 // 而值的改变会调用set,set中又会调用notify,notify中调用watcher的update方法实现了更新 this.$vm[exp] = newVal; }); }); } // 如果还有子节点,继续递归replaceTemplate if (node.childNodes && node.childNodes.length) {
this.replaceTemplate(node); } }); }}

使用

    
Document

{
{
song}}

主打歌为{

{
album.theme}}

作词人为{

{
singer}}等人。qq

转载地址:https://codeboy.blog.csdn.net/article/details/107440519 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:(精华)2020年7月19日 vue 缓存页面的强制更新
下一篇:(精华)2020年7月19日 vue vue-router(手写版)

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月10日 16时54分28秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章