markdown Vue反应系统

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown Vue反应系统相关的知识,希望对你有一定的参考价值。

## Vue Reactivty System

#### Step 1

1. Create state object and create function to render `y` to html

```
<h1 id="y"></h1>

let state = { x: 1 };
function renderY() {
  document.getElementById('y').innerText = `y = x + 1 = ${state.x + 1}`;
}
renderY();
```

#### Step 2

1. Instead of calling renderY function manually, we can create a setState function that updates our state and runs the render function

```
function setState(newState) {
  state = { ...state, ...newState} // newState Obj overrides original state obj prop
  renderY();
}
setState({ x: 2 });
```

1. Is there a way we can call the render function automatically when we update the state?
  
```javascript
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

let value = state['x']; // grab value of x
Object.defineProperty(state, 'x', {
  get() {
    return value; // simply return value 
  },
  set(newValue) {
    value = newValue; // update value
    renderY(); // run render function
  }
});
```

```
let state = { x: 1 };
function renderY() {
  document.getElementById('y').innerText = `y = x + 1 = ${state.x + 1}`;
}
renderY();

let value = state['x']; // grab value of x

Object.defineProperty(state, 'x', {
  get() {
    return value; // simply return value 
  },
  set(newValue) {
    value = newValue; // update value
    renderY(); // run render function
  }
});
```

1. Only works for property `x` and won't work for a nested object

#### Step 3

1. Create an observable function. This function simply loops through all the object keys, and recursively make ll nested objects observable.

```
function observable(obj) {
  Object.keys(obj).forEach(key => {
    let value = observable(obj[key);
    Object.defineProperty(obj, key, {
      get() {
        return value;
      },
      set(newValue) {
        value = newValue;
        renderY();
      }
    })
  });
  return obj;
}
```

```
function observable(obj) {
  Object.keys(obj).forEach(key => {
    let value = observable(obj[key]);
    Object.defineProperty(obj, key, {
      get() {
        return value;
      },
      set(newValue) {
        value = newValue;
        renderY();
      }
    });
  });
  return obj;
}

let state = observable({ x: 1 });

function renderY() {
  document.getElementById('y').innerText = `y = x + 1 = ${state.x + 1}`;
}

renderY();
```

1. Above, on state update, our code only does one job, which is to renderY, no matter which state updated. We have to figure out a way to make our observable state keep tracking what code is actually depending on state.

#### Step 4

1. To track code jobs dependency, create a simple Dep class. We can use it to create a dep instance for each objects key

```
class Dep {
  static job;
  constructor() {
    this.jobs = new Set();
  }
  depend() {
    if (Dep.job) {
      this.jobs.add(Dep.job);
    }
  }
  notify() {
    this.jobs.forEach(job => {
      job();
    })
  }
}
Dep.job = null;
```

1. In constructor, we create a jobs Set. We use Set bc we don't want duplicate jobs for the same key.
2. The depend method just adds a current job to the jobs set.
3. notify method runs all added jobs.
4. The static class variable `job` stores the current evaluating job. 

```
function observable(obj) {
  Object.keys(obj).forEach(key => {
    let value = observable(obj[key]);
    const dep = new Dep();
    
    Object.defineProperty(obj, key, {
      get() {
        dep.depend();
        return value;
      },
      set(newValue) {
        value = newValue;
        dep.notify();
      }
    });
  });
  return obj;
}
```

1. For each keywe create a new instance of Dep class to track the depended job
2. When renderY rund, the function trying to get state.x, so the getter for x will run, therefore, the renderY job will be added to the jobs set for x. 

```
class Dep {
  static job;
  constructor() {
    this.jobs = new Set();
  }
  depend() {
    if (Dep.job) {
      this.jobs.add(Dep.job);
    }
  }
  notify() {
    this.jobs.forEach(job => {
      job();
    });
  }
}
Dep.job = null;

function observable(obj) {
  Object.keys(obj).forEach(key => {
    let value = observable(obj[key]);
    const dep = new Dep();
    Object.defineProperty(obj, key, {
      get() {
        dep.depend();
        return value;
      },
      set(newValue) {
        value = newValue;
        dep.notify()
      }
    });
  });
  return obj;
}
  
let state = observable({
  x: 1
});

function renderY() {
  document.getElementById("y").innerText = `y = x + 1 = ${state.x + 1}`;
}

Dep.job = renderY;
renderY();
// dont forget clear the current job
Dep.job = null;
```

#### Step 5

```
class Dep {
  static job;
  constructor() {
    this.subscribers = new Set();
  }
  depend() {
    if (Dep.job) {
      this.subscribers.add(Dep.job);
    }
  }
  notify() {
    this.subscribers.forEach(sub => {
      sub();
    });
  }
}
Dep.job = null;

function observable(obj) {
  Object.keys(obj).forEach(key => {
    let value = observable(obj[key]);
    const dep = new Dep();
    Object.defineProperty(obj, key, {
      get() {
        dep.depend();
        return value;
      },
      set(newValue) {
        value = newValue;
        dep.notify()
      }
    });
  });
  return obj;
}
  
let state = observable({
  x: 1
});

function runner(job) {
  Dep.job = job;
  job();
  Dep.job = null;
}

function renderY() {
  document.getElementById("y").innerText = `y = x + 1 = ${state.x + 1}`;
}

runner(renderY);
runner(() => {
  document.getElementById("state").innerText = JSON.stringify(state, null, 2);
});
runner(() => {
  document.getElementById("x").innerText = `x = ${state.x}`;
});
```
1. Runner function
    1. takes a function and sets the function as the current job.
    2. Then run the job.
    3. Set the job back to null.
    
2. Observable function
    1. Loops through keys of the object passed in
    2. Sets value to the current obj[key] index
    3. Create new instance of the Dep class to track the depended job.
    4. 




以上是关于markdown Vue反应系统的主要内容,如果未能解决你的问题,请参考以下文章

vue项目解析markdown文件

markdown 反应数格式器

markdown 反应天然-火力

markdown 反应原生公地

markdown 反应模态警告

markdown 反应图表