From 2bd4e5bd815eb546c76b50aad08ef1ed5c223d26 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 18 Jun 2015 22:29:04 -0700 Subject: [PATCH] Remove fn.md The fn1 framework is deprecated. We don't need docs for it anymore. TBR=ianh@google.com Review URL: https://codereview.chromium.org/1189323002. --- sdk/lib/framework/README.md | 8 ++ sdk/lib/framework/fn.md | 222 ------------------------------------ 2 files changed, 8 insertions(+), 222 deletions(-) create mode 100644 sdk/lib/framework/README.md delete mode 100644 sdk/lib/framework/fn.md diff --git a/sdk/lib/framework/README.md b/sdk/lib/framework/README.md new file mode 100644 index 00000000000..fcb964f920b --- /dev/null +++ b/sdk/lib/framework/README.md @@ -0,0 +1,8 @@ +Legacy Framework +================ + +The code in this directory represents a previous iteration of the Sky framework +and will be removed at some point. + +The [current framework](../widgets/README.md) is availabe in +[`package:sky/widgets`](../widgets). diff --git a/sdk/lib/framework/fn.md b/sdk/lib/framework/fn.md deleted file mode 100644 index 40d964a8799..00000000000 --- a/sdk/lib/framework/fn.md +++ /dev/null @@ -1,222 +0,0 @@ -Sky Framework -============= - -(This file applies to fn.dart, which we are in the process of porting -to a new architecture.) - -Effen is a functional-reactive framework for Sky which takes inspiration from -[React](http://facebook.github.io/react/). Effen is comprised of three main -parts: a virtual-dom and diffing engine, a component mechanism and a very early -set of widgets for use in creating applications. - -The central idea is that you build your UI out of components. Components -describe what their view should look like given their current configuration & -state. The diffing engine ensures that the DOM looks how the component describes -by applying minimal diffs to transition it from one state to the next. - -If you just want to dive into code, see the [stocks example](../../../../examples/stocks). - -Hello World ------------ - -To build an application, create a subclass of App and instantiate it. - -```HTML - -``` - -```dart -// In hello_world.dart -import 'package:sky/framework/fn.dart'; - -class HelloWorldApp extends App { - UINode build() { - return new Text('Hello, world!'); - } -} -``` - -An app is comprised of (and is, itself, a) components. A component's main job is -to implement `UINode build()`. The idea here is that the `build` method describes -the DOM of a component at any given point during its lifetime. In this case, our -`HelloWorldApp`'s `build` method just returns a `Text` node which displays the -obligatory line of text. - -Nodes ------ - -A component's `build` method must return a single `UINode` which *may* have -children (and so on, forming a *subtree*). Effen comes with a few built-in nodes -which mirror the built-in nodes/elements of sky: `Text`, `Anchor` (``, -`Image` (``) and `Container` (`
`). `build` can return a tree of -Nodes comprised of any of these nodes and plus any other imported object which -extends `Component`. - -How to structure you app ------------------------- - -If you're familiar with React, the basic idea is the same: Application data -flows *down* from components which have data to components & nodes which they -construct via construction parameters. Generally speaking, View-Model data (data -which is derived from *model* data, but exists only because the view needs it), -is computed during the course of `build` and is short-lived, being handed into -nodes & components as configuration data. - -What does "data flowing down the tree" mean? --------------------------------------------- - -Consider the case of a checkbox. (i.e. `widgets/checkbox.dart`). The `Checkbox` -constructor looks like this: - -```dart - ValueChanged onChanged; - bool checked; - - Checkbox({ Object key, this.onChanged, this.checked }) : super(key: key); -``` - -What this means is that the `Checkbox` component *never* "owns" the state of -the checkbox. It's current state is handed into the `checked` parameter, and -when a click occurs, the checkbox invokes its `onChanged` callback with the -value it thinks it should be changed to -- but it never directly changes the -value itself. This is a bit odd at first look, but if you think about it: a -control isn't very useful unless it gets its value out to someone and if you -think about databinding, the same thing happens: databinding basically tells a -control to *treat some remote variable as its storage*. That's all that is -happening here. In this case, some owning component probably has a set of values -which describe a form. - -Stateful vs. Stateless components ---------------------------------- - -All components have access to two kinds of state: (1) configuration data -(constructor arguments) and (2) private data (data they mutate themselves). -While react components have explicit property bags for these two kinds of state -(`this.prop` and `this.state`), Effen maps these ideas to the public and private -fields of the component. Constructor arguments should (by convention) be -reflected as public fields of the component and state should only be set on -private (with a leading underbar `_`) fields. - -All (non-component) Effen nodes are stateless. Some components will be stateful. -This state will likely encapsulate transient states of the UI, such as scroll -position, animation state, uncommitted form values, etc... - -A component can become stateful in two ways: (1) by passing `super(stateful: -true)` to its call to the superclass's constructor, or by calling -`setState(Function fn)`. The former is a way to have a component start its life -stateful, and the latter results in the component becoming statefull *as well -as* scheduling the component to re-build at the end of the current animation -frame. - -What does it mean to be stateful? It means that the diffing mechanism retains -the specific *instance* of the component as long as the component which builds -it continues to require its presence. The component which constructed it may -have provided new configuration in form of different values for the constructor -parameters, but these values (public fields) will be copied (using reflection) -onto the retained instance whose privates fields are left unmodified. - -Rendering ---------- - -At the end of each animation frame, all components (including the root `App`) -which have `setState` on themselves will be rebuilt and the resulting changes -will be minimally applied to the DOM. Note that components of lower "order" -(those near the root of the tree) will build first because their building may -require rebuilding of higher order (those near the leaves), thus avoiding the -possibility that a component which is dirty build more than once during a single -cycle. - -Keys ----- - -In order to efficiently apply changes to the DOM and to ensure that stateful -components are correctly identified, Effen requires that `no two nodes (except -Text) or components of the same type may exist as children of another element -without being distinguished by unique keys`. [`Text` is excused from this rule]. -In many cases, nodes don't require a key because there is only one type amongst -its siblings -- but if there is more one, you must assign each a key. This is -why most nodes will take `({ Object key })` as an optional constructor -parameter. In development mode (i.e. when sky is built `Debug`) Effen will throw -an error if you forget to do this. - -Event Handling --------------- - -Events logically fire through the Effen node tree. If want to handle an event as -it bubbles from the target to the root, create an `EventListenerNode`. `EventListenerNode` -has named (typed) parameters for a small set of events that we've hit so far, as -well as a 'custom' argument which is a `Map`. If -you'd like to add a type argument for an event, just post a patch. - -```dart -class MyComp extends Component { - MyComp({ - Object key - }) : super(key: key); - - void _handleTap(sky.GestureEvent e) { - // do stuff - } - - void _customEventCallback(sky.Event e) { - // do other stuff - } - - UINode build() { - new EventListenerNode( - new Container( - children: // ... - ), - onGestureTap: _handleTap, - custom: { - 'myCustomEvent': _customEventCallback - } - ); - } - - _handleScroll(sky.Event e) { - setState(() { - // update the scroll position - }); - } -} -``` - -Styling -------- - -Styling is the part of Effen which is least designed and is likely to change. -There are three ways to specify styles: - - * `Style` objects which are interned and can be applied to WrapperNodes via the - ``style` constructor parameter. Use `Style` objects for styles which are - `*not* animated. - - * An `inlineStyle` string which can be applied to Elements via the - `inlineStyle` constructor parameter. Use `inlineStyle` for styles which - *are* animated. - -If you need to apply a Style to a Component or UINode which you didn't construct -(i.e. one that was handed into your constructor), you can wrap it in a -`StyleNode` which also takes a `Style` constructor in it's `style` constructor -parameter. - -Animation ---------- - -Animation is still an area of exploration. Have a look at -[AnimatedComponent](components/animated_component.dart) and -[Drawer](components/drawer.dart) for an example of this this currently works. - -Performance ------------ - -It is a design goal that it should be *possible* to arrange that all "build" -cycles which happen during animations can complete in less than one milliesecond -on a Nexus 5.