Silentdoer

导航

Flutter随记

【注意,运行dart命令不要在git bash里,很有问题,特别是执行flutter pub get这种命令】

1.Flutter SDK下载配置好环境变量后,在VSCode里安装dart和flutter两个插件后就可以创建项目了;

2.创建项目可以用命令flutter create demo_01,则会自动创建demo_01项目目录(注意项目不要用demo-01而是用下划线)【可以加 --no-pub来不自动执行pub get】

3.Flutter里布局是根据Widget类型来实现的,比如Scaffold是具有appBar和body和floatingActionButton等三个布局块(上下分列,最后的那个其实是一个floatting的一个控件)的一个Widget(在C#里叫Control/控件),

而Center这种代表它内部只有一个布局块(但是是全局居中对齐)【只有一个布局块的内容属性一般都叫child】

而像Row,Column之类的则有多个元素,因此表示内容的属性叫children(注意,Column是一列而非Columns多列,因此Column的子元素是在这一列里上下排列的)

4.flutter创建项目还可以flutter create --no-pub --platforms=windows ft_demo01来创建指定目标源的项目(如果已经创建项目,可以用flutter create --platforms=linux .);如果对这个项目需要增加目标源,可以执行flutter  devices查看本机flutter配置了哪些目标源,然后cd到项目根目录后通过flutter config --enable-linux-desktop来启用某个目标源(这里是Linux desktop,还有--enable-windows-desktop);注意启用了目标源需要重新创建一下项目,即再执行flutter create --no-pub .;然后手动执行 flutter  pub get --offline后就可以通过 flutter run -d windows来debug此目标源;还可以用flutter build windows(可以加--release)来build此目标源;

5.shift+r可以热重启【r是热重载】【dart不行,要借助pub包】

6.事件冒泡(包括前端)的意思是,比如有这种情况,一个Panel里面有个ListView,而Panel注册了双击左侧按钮事件(比如双击Panel会提示啥),而ListView的item也注册了双击事件;因此ListView的item这个组件是Panel的子孙组件,当双击item的时候事件被item先监听处理,如果不阻止冒泡,则会继续让Panel也处理这个双击事件;(还有典型的场景为外层是一个ScrollView,而内部子孙里也有ScrollView,因此对子孙Scroll时产生的事件如果不取消冒泡,则父Scroll也能收到,就会发生两个ScrollView一起动的情况)

7.flutter里一个新的页面(路由页面)其实就是一个ConstrainedBox【expand()的】,因此对Container设置大小不生效;但是可以先用UnconstrainedBox包裹后,再用Container、SizedBox、ConstrainedBox等就有用了;【即如果父组件是ConstrainedBox,设置了最小长宽,则其子容器设置的大小如果小于父ConstrainedBox则以父ConstrainedBox为主(可以用UnconstrainedBox来取消父ConstrainedBox对子组件的影响,但是父ConstrainedBox大小是不受影响的);ConstrainedBox优先级大于SizedBox(也不能这么说,应该说这两个谁是父组件则谁的优先级更高)】【但是注意,ConstrainedBox和SizedBox对子元素的大小限制是基于子元素是单个控件组成的,比如各种容器,各种button(容器和button等是child);而如果子元素是Row这种的,则Row里的children元素是不会和ConstrainedBox等一样宽/高的】【或者这么讲,Row等默认外面就包有一层UnconstrainedBox】

8.UnconstrainedBox对SizedBox也有取消作用

9.Scrollbar不是ScrollView;ListView【ScrollView子类】内部的ListView必须外面包一层具体height的容器;或者将这个内部ListView的shrinkWrap: true

10.flutter没法在局部容器里实现css的fixed,flutter里要实现绝对定位目前查到的还是得用Stack+Positioned,Stack的面积大小取决于它最大的那个子元素;所以Stack是一定有面积的除非所有子元素都是空面积;然后最大的一点不能在局部Stack里实现fixed的原因是Positioned定位的位置如果超过了Stack的面积范围【跑其他元素上了】就会被其他元素给遮蔽看不见,因此要实现fixed其实就是要求页面第一个有面积的元素就必须是Stack才行;

11.可以用FractionallySizedBox(heightFactor: .5, widthFactor: .5, child: Container(color: Colors.deepOrange,)来实现设置容器的长宽是父元素的一半(按比例);

也可以通过这种方式来实现:(LayoutBuilder可以获取到父元素的最大大小,大多数情况下最大大小就是父容器的大小但是父容器是LimitedBox等的时候则不是)

LayoutBuilder(
                  builder: (context, constraints) {
                    return UnconstrainedBox(
                        child: Container(
                            color: Colors.deepOrange,
                            height: constraints.maxHeight / 2,
                            width: constraints.maxWidth / 2));
                  },
                )

 12.flutter离线创建项目(需要把.pub-cache的东西复制到离线机器里,似乎hosted里的就行了【放到对应的仓库目录下】):flutter create --offline demo01【但是目前还没有发现怎么禁止flutter访问github,它要超时后才会开始创建项目(解决方法是离线环境机/无法连flutter网的机器里不要配置任何flutter的环境变量,比如PUB_HOSTED_URL【添加path变量除外】)】,然后再进入项目用flutter pub get --offline;然后就可以flutter run -d chrome来运行了【注意,如果没有安装Chrome,则可以用flutter run -d web-server,然后启动后在终端上会出现地址,复制到浏览器运行即可(要现代浏览器)【如果不行可能需要重启一次电脑;如果是某个特定的项目不行,比如是template项目,则可以考虑将main.dart的代码改成初始化生成的代码,那这时候r reload一下一般页面是能显示加数字的页面了,这个时候再改回去template的代码,然后再r reload一下就能发现template也能显示了;flutter3.3.7版本离线没有问题,3.10.6有问题;还有可能出现中文乱码问题,这个可以从windows里复制宋体到项目根目录下fonts目录里,然后在pubspec.yaml里配置字体后,然后在main.dart里的theme里配置全局使用字体】;

还可能得下载一个C#包管理器nuget.exe,然后把它所在的目录加入到Path,通过nuget.exe help如果没问题则ok(目前至少是要6.5版本nuget)

离线创建项目用命令:flutter create --offline test01 -v,-v可以看到详情,如果对旧项目执行失败可以先flutter clean一下然后在flutter pub get --offline -v,然后再重新run

fluter web可以下载一下这个资源文件:https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf,然后flutter build web后,开启根目录是build/web的server,访问http://localhost:port/index.html,可以改写此web应用里面的获取该ttf资源的代码为从本地获取,方式为:找到build/web里的main.dart.js,搜索ttf就能找到这块代码,可以改成如http://localhost:port/KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf

13.如果发现运行有问题,可以考虑将build目录下相关target环境(如windows)目录删除重新运行

flutter调试的时候,不能开启代理,否则无法hotreload;

14.flutter 3.10之后将flutter web应用打包的内容之间嵌入到已有项目的div元素里的办法:

1.先用flutter build web编译出(可以考虑加wasm选项)web项目,在build/web目录下;
2.将build/web目录下的assets目录+flutter.js+main.dart.js单独拿出来,这几个就可以用于嵌入到已有html文件的某个元素上;
3.搜索main.dart.js里的 KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf 文件,可以看到是请求的:https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf
将其改成:/KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf,假设这个资源是放在项目根目录下,如果不是则自己加前缀;
3.假设要嵌入到proja目录下的index.html文件里的<div id="flutter_host"></div>元素上(这个元素是单独加上去的,用于挂载编译好的flutter组件)
然后在index.html里添加这样几行代码:
一是在<head><script src="flutter.js" defer></script></head>,这里的src路径根据实际情况来写;
二是在<body>最后的
<script>
    window.addEventListener('load', function(ev) {
        _flutter.loader.loadEntrypoint({
            onEntrypointLoaded: async function(engineInitializer) {
                let appRunner = await engineInitializer.initializeEngine({
                    hostElement: document.querySelector("#flutter_host")
                });
                await appRunner.runApp();
            }
        });
    });
</script>
这里可以限制<div id="flutter_host"></div>元素的宽高

如果是vue项目也是类似,flutter.js应该也是直接放index.html里加载,但是flutter_host元素则可以放具体的页面里去,body最后的script则不应该放index.html里,而是具体组件里了;

具体一点可以是放到vue3项目里src/assets/ft_component_foo(这个foo是组件名,一个vue项目里可以有多个flutter编译出的组件)里放flutter web打包后的的assets目录+flutter.js+main.dart.js这三个文件,而ttf资源文件由于具有共性直接放上层即src/assets目录(flutter.js不知道在多个flutter web项目编译出来后是不是也是一样的,如果也是一样的也可以放到src/assets里),然后基于这个路径去改main.dart.js里的相关资源加载路径,比如../KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf,在index.html的head里添加<script src="/src/assets/ft_component_foo/flutter.js" defer></script>

【经过测试,和单页应用整合的不行,一个html页面只能嵌一个flutter web,就没啥用,还不如用iframe嵌】

posted on 2021-08-09 21:53  Silentdoer  阅读(138)  评论(0编辑  收藏  举报