编译产物 JSON 文件详解

Wuba2022年11月7日大约 3 分钟

本文将为你介绍编译产物之一 JSON 文件的结构。

为了便于讲解,我们用一个例子来说明:

import 'package:fair/fair.dart';
import 'package:flutter/material.dart';

()
class JsonFileExplain extends StatefulWidget {
  const JsonFileExplain({Key? key}) : super(key: key);

  
  _JsonFileExplainState createState() => _JsonFileExplainState();
}

class _JsonFileExplainState extends State<JsonFileExplain> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  Widget _buildTitle() {
    return Text('title');
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: _buildTitle(),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: TextStyle(
                  fontSize: 40, color: Color(0xffeb4237), wordSpacing: 0),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

执行:flutter pub run build_runner build 命令后,生成了 JSON 文件,我们打开文件看看:

{
  "className": "Scaffold",
  "na": {
    "appBar": {
      "className": "AppBar",
      "na": {
        "title": "%(_buildTitle)"
      }
    },
    "body": {
      "className": "Center",
      "na": {
        "child": {
          "className": "Column",
          "na": {
            "mainAxisAlignment": "#(MainAxisAlignment.center)",
            "children": [
              {
                "className": "Text",
                "pa": [
                  "You have pushed the button this many times:"
                ]
              },
              {
                "className": "Text",
                "pa": [
                  "#($_counter)"
                ],
                "na": {
                  "style": {
                    "className": "TextStyle",
                    "na": {
                      "fontSize": 40,
                      "color": {
                        "className": "Color",
                        "pa": [
                          "0xffeb4237"
                        ]
                      },
                      "wordSpacing": 0
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "floatingActionButton": {
      "className": "FloatingActionButton",
      "na": {
        "onPressed": "@(_incrementCounter)",
        "tooltip": "Increment",
        "child": {
          "className": "Icon",
          "pa": [
            "#(Icons.add)"
          ]
        }
      }
    }
  },
  "methodMap": {
    "_buildTitle": {
      "className": "Text",
      "pa": [
        "title"
      ]
    }
  }
}

在 JSON 文件中,有几个重要的 key:

  • className
  • na
  • pa
  • methodMap

下面详细为你解释每一个 key 的含义。

1. className

className 表示对于的 Widget 的名字,如 JSON 文件第一行:"className": "Scaffold",它对应的是 build 方法里面的 Scaffold

image.png

2.naopen in new window

na表示 命名可选参数。如示例代码中的 Scaffold 的 3 个命名可选参数 appBarbodyfloatingActionButton ,都会被存放在 JSON 文件的 na 中。

image.png

3.paopen in new window

pa表示 required 类型。如示例代码的 Text 中的 required 参数:String data

image.png

4.methodMap

methodMap表示在 State 中用于返回 Widget 的方法,如:


class _JsonFileExplainState extends State<JsonFileExplain> {
  
  ......

  Widget _buildTitle() {
    return Text('title');
  }
}

image.png

注意,一定要通过 return 的方式去返回 Widget,这样 Fair 才能正确解析。

好,到这里,我们已经把所有 key 的含义讲清楚了。但是,也许你还有疑问,JSON 文件里的 %@#^等符号是什么意思呢?

别着急,下面我们继续为你介绍。

布局中如果引用了变量、常量和方法在解析成 DSL 时都会被当成一个字符串,像这样:

image.png 为了方便在解析 DSL 时区分不同字符串的含义,我们在字符串的前面加上了不同的特殊符号,具体包括:

1.% 代表引用的是一个返回值为 Widget 的方法

image.pngTips:注意只有在布局中引用了返回值是 Widget 的方法时,才会被标记上%符号。

2.@ 代表引用的是一个非 Widget 的方法

image.pngTips:注意只有在布局中引用的方法的返回值,不是一个 Widget 时,才会被标记为@符号。返回值可以是 void ,也可以是 Dart 支持的数据类型,如 int、String、Boolean 等。

3.# 代表引用的是一个外部变(常)量或者 $ 符号引用的本地变量

外部变(常)量比如:MainAxisAlignment.centerIcons.addimage.png

image.png

还有一种情况是,使用了 $ 符号引用了本地变量或者进行了字符串拼接(aaaa$_counter):

image.png

4.^ 代表直接引用的是一个本地实例变量

image.png

上次编辑于:
贡献者: sunzhe03