上篇文章中主要介绍了Solid JS的基本语法,分阶段粗略地介绍了一些原理(响应式原理、编译原理和运行时原理)。

在纳溪等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供网站设计、做网站 网站设计制作按需搭建网站,公司网站建设,企业网站建设,高端网站设计,营销型网站建设,成都外贸网站建设公司,纳溪网站建设费用合理。
接下来的几篇文章里我会详细介绍每个阶段的详细实现原理,希望可以给你的学习带来帮助。
写这篇文章的时候有很大的犹豫,担心Solid JS受众太小,文章的反响连”平平“都算不上,所以先写一篇试试水,如果真的反响平平,我会暂时放弃这个写作计划,还请见谅!
作为Solid JS响应式的基石,我们先看看createSignal的用法和原理。接着我们手动实现一个简易版的createSignal,
function createSignal(
    initialValue: T,
    options?: { equals?: false | ((prev: T, next: T) => boolean) }
): [get: () => T, set: (v: T) => T]; Solid JS的厉害之处是,你可以定义变量是否为响应式,甚至可以定义响应式的时机。
下面这个例子仅仅在新的值大于旧的值(新增)时,才是响应式的。
import { render } from "solid-js/web";
import { createSignal } from "solid-js";
function Counter() {
  const [count, setCount] = createSignal(1, { equals: (n, o) => n > o });
  const increment = () => setCount(count() + 1);
  const reduce = () => setCount(count() - 1);
  return (
    <>
      
      
      
    >
  );
}
render(() => createSignal简化后的逻辑如下:
const signalOptions = {
  equals: false
};
function createSignal(value, options) {
  // 初始化options
  options = options
      ? Object.assign({}, signalOptions, options)
      : signalOptions;
  // 创建内部signal
  const s = {
    value,
    comparator: options.equals || undefined
  };
 
  // 定义setter
  const setter = value => {
    if (typeof value === "function") {
      value = value(s.value);
    }
    return writeSignal(s, value);
  };
  // 返回[getter, setter]
  return [readSignal.bind(s), setter];
}
// 返回当前内部signal的value
function readSignal() {
  return this.value;
}
// 更新内部的value,然后返回value
function writeSignal(node, value) {
  if (!node.comparator) {
    node.value = value;
  }
  return value;
}现在我们已经实现了createSignal基本功能了,接下来我们通过实现createEffect来让它具有响应式的能力。
createEffect接受一个副作用函数,每当它依赖的状态发生改变时,这个副作用都被执行一次。
function createEffect(fn: (v: T) => T, value?: T): void; 这是个很常见的例子。
import { render } from "solid-js/web";
import { createSignal, createEffect } from "solid-js";
function Counter() {
  const [count, setCount] = createSignal(1);
  const increment = () => setCount(count() + 1);
  createEffect(() => console.log('count : ', count()))
  return (
    
  );
}
render(() => 我们已经知道,当createEffect依赖项发生改变时,副作用会也会发生改变,这是因为createSignal是基于发布订阅模式的响应式。一个较为完整的关系如下:
const signalOptions = {
  equals: false
};
const observers = []
function createEffect (effect) {
  const execute = () => {
    // 保存在observers中
    observers.push(execute);
    try {
      effect();
    } finally {
      // 释放
      observers.pop();
    }
  };
  // 副作用函数立即执行
  execute();
};
function createSignal(value, options) {
  // 初始化options
  options = options
      ? Object.assign({}, signalOptions, options)
      : signalOptions;
  // 创建内部signal
  const s = {
    value,
    // 保存订阅者
    subscribers: new Set(),
    comparator: options.equals || undefined
  };
 
  // 定义setter
  const setter = value => {
    if (typeof value === "function") {
      value = value(s.value);
    }
    return writeSignal(s, value);
  };
  // 返回[getter, setter]
  return [readSignal.bind(s), setter];
}
// 返回当前内部signal的value
function readSignal() {
  const curr = observers[observers.length - 1]
  curr && this.subscribers.add(curr)
  return this.value;
}
// 更新内部的value,然后返回value
function writeSignal(node, value) {
  if (!node.comparator) {
    node.value = value;
  }
  // 每次写入时执行对应的订阅者
  node.subscribers.forEach((subscriber) => subscriber());
  return value;
}现在我们准备下面的html文件
  
  
  
  SolidJS 
  打开控制台查看结果
  
  
使用window.increment模拟点击事件,打印如下。
下面我们实现createMemo
createMemo通常用来做派生变量保存基于某个状态中间值。完整用法如下:
function createMemo(
    fn: (v: T) => T,
    value?: T,
    options?: { equals?: false | ((prev: T, next: T) => boolean) }
): () => T; 本篇只讨论最原始的memo。
一个例子如下,每当count变化时,sum自动加2
import { render } from "solid-js/web";
import { createSignal, createEffect, createMemo } from "solid-js";
function Counter() {
  const [count, setCount] = createSignal(1);
  const increment = () => setCount(count() + 1);
  const sum = createMemo(() => count() + 2)
  
  createEffect(() => console.log('sum : ', sum()))
  
  createEffect(() => console.log('count : ', count()))
  
  return (
    
  );
}
render(() => 它的内部是使用createSignal实现的,所以流程上来说和createEffect一样。
真实的源码里,是基于createComputation实现的,但是它的内部是createSignal
const createMemo = (memo) => {
  const [value, setValue] = createSignal();
  createEffect(() => setValue(memo()));
  return value;
};接下来在测试例子里添加如下两行
const sum = createMemo(() => count() + 2)
createEffect(() => console.log('sum : ', sum()))然后在控制台操作