From c1abe1f9003984cd81e8dd4801a42a15d849a8f8 Mon Sep 17 00:00:00 2001 From: Jim Date: Tue, 3 Mar 2015 17:51:10 -0800 Subject: [PATCH] Declarative jsx22 example --- .../01 - Complex Structure.js | 94 +++++++++++++++++++ .../02 - Tag Implementations.js | 35 +++++++ 2 files changed, 129 insertions(+) create mode 100644 10 - More Declarative JSX/01 - Complex Structure.js create mode 100644 10 - More Declarative JSX/02 - Tag Implementations.js diff --git a/10 - More Declarative JSX/01 - Complex Structure.js b/10 - More Declarative JSX/01 - Complex Structure.js new file mode 100644 index 0000000..73d9127 --- /dev/null +++ b/10 - More Declarative JSX/01 - Complex Structure.js @@ -0,0 +1,94 @@ + + +// This feature does NOT propose the addition of special templating tags. It only introduces the ability for tags to bind +// variables, thereby allowing custom components that can be composed in a way that is more readable and feels more declarative. +// We assume implementations of "push", "if" and "foreach" tags. The actual implementation is quite trivial, and +// implementable by the end user. + + +// Currently, to render a bookstore, you would need the following code... +var booksData = [{title: "Harry Potter", authors: ["JK Rowling"], ...}, ...]; +return
{booksData.map(function(bookData){ + var authorElements = []; + bookData.authors.foreach(function(authorData, idx){ + authorElements.push({author.name}); + if(idx !== bookData.authors.length) authorElements.push(", "); + }); + return
+

{bookData.title}

+ By: + { bookData.authors.length === 0 ? Unknown author : {authorElements}} +
; +})}
; + + +// The problem is that the code above is complex and hard to follow. it feels a lot like back in the days when +// user interfaces were built using an imperative API (like IOS, Swing, etc). +// In order to generate the comma-separated list of authors for each book, we had to create a new array, iterate over +// the data, and push elements into the new array, and subsequently put the array of elements into the markup. +// This was a simple example, but you can imagine this widget becoming much more complicated, and it becoming hard +// to track what's happening in the user interface + +// Now let's try something new. + +// Ideally, you could do the same thing in a less imperative way by evaluating variables lazily... + +
+ +
+

{title}

+ By: + + Unknown author + + 0}> + + {author.name} + + , + + +
+
+
+
+ + +// The declarative example is much more readable. And the readability benefits grow super-linearly with component complexity. + + + +// Now suppose we get a request from our designers to insert a
element between each of our book div tags. +// With the declarative model, it's really easy. + +
+ +
+

{title}

+ By: + + Unknown author + + 0}> + + {author.name} + + , + + +
+ +
+
+
+
+
+ + +// I'll leave it as an exercise for the reader to figure out how to do this with the current imperative-ish code +// It is an informative exercise, because you realize how tricky it really is once you attempt to modify the code. + diff --git a/10 - More Declarative JSX/02 - Tag Implementations.js b/10 - More Declarative JSX/02 - Tag Implementations.js new file mode 100644 index 0000000..750c749 --- /dev/null +++ b/10 - More Declarative JSX/02 - Tag Implementations.js @@ -0,0 +1,35 @@ + + +// I previously claimed that the implementation of "push", "iff", and "foreach" were trivial. +// We don't need to provide default implementations, but we should allow for them to exist. +// Here are my implementations, exact syntax of which is to be determined, but you get the idea + +class push { + render: function() { + return this.context.push(this.props.name, this.props.value, this.children); + } +} + +class iff { + render: function() { + return this.props.test === true ? this.props.children : null; + } +} + +class foreach { + render: function() { + this.props.collection.map(function(element, index) { + return ( + + + {this.props.children} + + + ); + }); + } +} + +// Alternate syntaxes might look less like "traditional jsx" but could allow additional performance +// benefits (like short-circuit evaluation for children that will never render). +