|
svelte文件编译为js后的结构
源代码:-
-
- <p>fullName is {firstName} {lastName}</p>
- <p>age is {age}</p>
-
- <button on:click={handleChangeName}>change name</button>
- <button on:click={handleChangeAge}>change age</button>
-
-
复制代码 编译后的js代码结构- function create_fragment(ctx) {
- const block = {
- c: function create() {
- // ...
- },
- m: function mount(target, anchor) {
- // ...
- },
- p: function update(ctx, [dirty]) {
- // ...
- },
- d: function destroy(detaching) {
- // ...
- }
- };
- return block;
- }
- function instance($$self, $$props, $$invalidate) {
- let firstName = '张';
- let lastName = '三';
- let age = 18;
- function handleChangeName() {
- $$invalidate(0, firstName = '王');
- $$invalidate(1, lastName = '二');
- }
- function handleChangeAge() {
- $$invalidate(2, age = 28);
- }
- return [firstName, lastName, age, handleChangeName, handleChangeAge];
- }
- class Name extends SvelteComponentDev {
- constructor(options) {
- init(this, options, instance, create_fragment, safe_not_equal, {});
- }
- }
复制代码 初始化调用init方法
- function init(component, options, instance, create_fragment, ...,dirty = [-1]) {
- // $$属性为组件的实例
- const $$ = component.$$ = {
- ...
- // dirty的作用是标记哪些变量需要更新,
- // 在update生命周期的时候将那些标记的变量和对应的dom找出来,更新成最新的值。
- dirty,
- // fragment字段为一个对象,对象里面有create、mount、update等方法
- fragment: null,
- // 实例的ctx属性是个数组,存的是组件内的顶层变量、方法等。按照定义的顺序存储
- ctx: [],
- ...
- }
- // ctx属性的值为instance方法的返回值。
- // instance方法就是svelte文件编译script标签代码生成的。
- // instance方法的第三个参数为名字叫$$invalidate的箭头函数,
- // 在js中修改变量的时候就会自动调用这个方法
- $$.ctx = instance
- ? instance(component, options.props || {}, (i, ret, ...rest) => {
- const value = rest.length ? rest[0] : ret;
- if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
- make_dirty(component, i);
- }
- return ret;
- })
- : [];
- // 调用create_fragment方法
- // 并且在后续对应的生命周期里面调用create_fragment方法返回的create、mount、update等方法
- $$.fragment = create_fragment ? create_fragment($$.ctx) : false;
- }
复制代码 点击change name按钮,修改firstName和lastName的值
- let firstName = '张'
- let lastName = '三'
- let age = 18
- function handleChangeName() {
- // firstName变量第一个定义,所以这里是0,并且将新的firstName的值传入$$invalidate方法
- $$invalidate(0, firstName = '王');
- // lastName变量第二个定义,所以这里是1,并且将新的firstName的值传入$$invalidate方法
- $$invalidate(1, lastName = '二');
- }
- // ...
复制代码 再来看看invalidate函数的定义,invalidate函数就是在init时调用instance的时候传入的第三个参数- (i, ret, ...rest) => {
- // 拿到更新后的值
- const value = rest.length ? rest[0] : ret;
- // 判断更新前和更新后的值是否相等,不等就调用make_dirty方法
- if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
- // 第一个参数为组件对象,第二个参数为变量的index。
- // 当更新的是firstName变量,firstName是第一个定义的,所以这里的i等于0
- // 当更新的是lastName变量,lastName是第二个定义的,所以这里的i等于1
- make_dirty(component, i);
- }
- return ret;
- }
复制代码 make_dirty方法的定义- function make_dirty(component, i) {
- // dirty初始化的时候是由-1组成的数组,dirty[0] === -1说明是第一次调用make_dirty方法。
- if (component.$$.dirty[0] === -1) {
- dirty_components.push(component);
- // 在下一个微任务中调用create_fragment方法生成对象中的update方法。
- schedule_update();
- // 将dirty数组的值全部fill为0
- component.$$.dirty.fill(0);
- }
- component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
- }
复制代码 再来看看component.$$.dirty[(i / 31) | 0] |= (1 |
|