ustccjw / rax

[ 🚧Work In Progress v1.0] The fastest way to build cross-container application.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rax

[🚧 Work In Progress v1.0] The fastest way to build cross-container application.

gzip size


âš¡ Fast: blazing fast virtual DOM.

🎯 Tiny: ~7 KB minified + gzipped.

🎨 Universal: works with DOM, Weex, Node.js, Mini-program, WebGL and could works more container that implement driver specification.

Quick Start

Using via CLI

Install the Rax CLI tools to init project:

$ npm install rax-cli -g
$ rax init <YourProjectName>

Start local server to launch project:

$ cd YourProjectName
$ npm run start

Using via CDN

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://unpkg.com/rax@1.0.0-beta.13/dist/rax.js"></script>
    <script src="https://unpkg.com/driver-dom@1.0.0-beta.4/dist/driver-dom.js"></script>
    
    <!-- Don't use this in production: -->
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="text/babel">
      // @jsx Rax.createElement
      Rax.render(
        <h1>Hello, world!</h1>,
        document.getElementById('root'),
        { driver: DriverDOM }
      );

    </script>
  </body>
</html>

About JSX(XML-like syntax extension to ECMAScript)

Each JSX element is just syntactic sugar for calling createElement(component, props, ...children). So, anything you can do with JSX can also be done with just plain JavaScript.

// Hello.jsx
import {createElement, useState} from 'rax';

export default (props) => {
  const [name, setName] = useState(props.name);
  const handleClick = () => {
    setName('rax');
  };
  return (
    <div style={styles.hello}>
      <span style={styles.title} onClick={handleClick}>
      Hello {name}
      </span>
    </div>
  );
}

const styles = {
  hello: {
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center'
  },
  title: {
    fontSize: '40px',
    textAlign: 'center'
  }
};
// app.js
import {render} from 'rax';
import DriverDOM from 'driver-dom';
import Hello from './Hello';

render(<Hello name="world" />, document.body, { driver: DriverDOM });

Rax API (v1.0)

Creating Elements

  • createElement(type, [props], [...children])
createElement('div', { id: 'foo' }, createElement('p', null, 'hello world'));

Fragments

  • Fragment
    <Fragment>
      <header>A heading</header>
      <footer>A footer</footer>
    </Fragment>

Refs

  • createRef()
    const inputRef = createRef();
    function MyComponent() {
      return <input type="text" ref={inputRef} />;
    }
  • forwardRef()
    const MyButton = forwardRef((props, ref) => (
      <button ref={ref}>
        {props.children}
      </button>
    ));
    
    // You can get a ref directly to the DOM button:
    const ref = createRef();
    <MyButton ref={ref}>Click me!</MyButton>;

Hooks

  • useState()
    function Example() {
      // Declare a new state variable, which we'll call "count"
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>
            Click me
          </button>
        </div>
      );
    }
  • useEffect()
    function Example() {
      const [count, setCount] = useState(0);
    
      // Similar to componentDidMount and componentDidUpdate:
      useEffect(() => {
        document.title = `You clicked ${count} times`;
      });
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>
            Click me
          </button>
        </div>
      );
    }
  • useLayoutEffect()
    function Example() {
      const [count, setCount] = useState(0);
    
      useLayoutEffect(() => {
        // Fires in the same phase as componentDidMount and componentDidUpdate
      });
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>
            Click me
          </button>
        </div>
      );
    }
  • useContext()
    // Create a Context
    const NumberContext = createContext();
    
    function Example() {
      const value = useContext(NumberContext);
      return <div>The answer is {value}.</div>;
    }
  • useRef()
    function TextInputWithFocusButton() {
      const inputEl = useRef(null);
      const onButtonClick = () => {
        // `current` points to the mounted text input element
        inputEl.current.focus();
      };
      return (
        <>
          <input ref={inputEl} type="text" />
          <button onClick={onButtonClick}>Focus the input</button>
        </>
      );
    }
  • useCallback()
    const memoizedCallback = useCallback(
      () => {
        doSomething(a, b);
      },
      [a, b],
    );
  • useMemo()
    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • useReducer()
    const initialState = {count: 0};
    
    function reducer(state, action) {
      switch (action.type) {
        case 'reset':
          return initialState;
        case 'increment':
          return {count: state.count + 1};
        case 'decrement':
          return {count: state.count - 1};
        default:
          // A reducer must always return a valid state.
          // Alternatively you can throw an error if an invalid action is dispatched.
          return state;
      }
    }
    
    function Counter({initialCount}) {
      const [state, dispatch] = useReducer(reducer, {count: initialCount});
      return (
        <>
          Count: {state.count}
          <button onClick={() => dispatch({type: 'reset'})}>
            Reset
          </button>
          <button onClick={() => dispatch({type: 'increment'})}>+</button>
          <button onClick={() => dispatch({type: 'decrement'})}>-</button>
        </>
      );
    }
  • useImperativeHandle()
    function FancyInput(props, ref) {
      const inputRef = useRef();
      useImperativeHandle(ref, () => ({
        focus: () => {
          inputRef.current.focus();
        }
      }));
      return <input ref={inputRef} />;
    }
    FancyInput = forwardRef(FancyInput);

Performance

  • memo()
    function MyComponent(props) {
      /* render using props */
    }
    function areEqual(prevProps, nextProps) {
      /* 
        return true if passing nextProps to render would return
        the same result as passing prevProps to render,
        otherwise return false
      */
    }
    export default memo(MyComponent, areEqual);

Rendering Elements

  • render(element [, container] [, options] [, callback])
    render(<HelloMessage name="world" />, document.body, { driver: DomDriver })

Version

  • version

rax-children

  • Children
    • Children.map(children, function[(thisArg)])
    • Children.forEach(children, function[(thisArg)])
    • Children.count(children)
    • Children.only(children)
    • Children.toArray(children)

rax-proptypes

  • PropTypes
    • PropTypes.array
    • PropTypes.bool
    • PropTypes.func
    • PropTypes.number
    • PropTypes.object
    • PropTypes.string
    • PropTypes.symbol
    • PropTypes.element
    • PropTypes.node
    • PropTypes.any
    • PropTypes.arrayOf
    • PropTypes.instanceOf
    • PropTypes.objectOf
    • PropTypes.oneOf
    • PropTypes.oneOfType
    • PropTypes.shape

rax-is-valid-element

  • isValidElement(object)

rax-clone-elment

  • cloneElement(element, [props], [...children])

rax-create-factory

  • createFactory(type)

rax-create-portal

  • createPortal(child, container)

rax-hydrate

  • hydrate(element, container[, callback])

rax-find-dom-node

  • findDOMNode(component)

rax-unmount-component-at-node

  • unmountComponentAtNode(container)

Rax Legacy API (v1.0)

rax-component

  • Component

rax-pure-component

  • PureComponent

rax-create-class

  • createClass()

Rax Official Hooks

Asynchronous Operation

import { createElement, useMemo } from 'rax';
import usePromise from 'rax-use-promise';

const fetchData = () => fetch('https://httpbin.org/get').then(res => res.json());

function Example() {
  const [data, error] = usePromise(useMemo(fetchData));
  if (error) {
    return <p>error</p>
  } else if (data) {
    return <p>{data.foo}</p>
  }
}

Fetch Data

import { createElement } from 'rax';
import useFetch from 'rax-use-fetch';

function Example() {
  const [data, error] = useFetch('https://httpbin.org/get');
  if (error) {
    return <p>error</p>
  } else if (data) {
    return <p>{data.foo}</p>
  } else {
    return <p>loading</p>
  }
}

Router

import { createElement, Fragment } from 'rax';
import { route, useComponent, push } from 'rax-use-router';
import Foo from './Foo';

route([{
  path: '/home',
  routes: [
    {
      path: '',                   // www.example.com/home
      component: () => <>
        <button onClick={() => push('/foo')}>go foo</button>
        <button onClick={() => push('/bar')}>go bar</button>
        <button onClick={() => push('/home/jack')}>go jack</button>
      </>,
    },
    {
      path: '/:username',         // www.example.com/home/xxx
      component: (params) => <>
        <p>{params.username}</p>
        <button onClick={ () => push('/home') }>Go home</button>
      </>
    }
  ]},
  {
    path: '/bar',
    routes: [
      {
        path: '',                 // www.example.com/bar
        component: () => import(/* webpackChunkName: "bar" */ './Bar'),
      },
    ],
  },
  {
    path: '/foo',                 // www.example.com/foo
    component: () => <Foo />,  
  },
]);

export default function Example() {
  var component = useComponent('/home');
  return component;
}
// Foo.jsx
import { createElement } from 'rax';
import { push } from 'rax-use-router';

export default function Foo() {
  return <button onClick={ () => push('/home') }>Go home</button>
}
// Bar.jsx
import { createElement } from 'rax';
import { push } from 'rax-use-router';

export default function Bar() {
  return <button onClick={ () => push('/home') }>Go home</button>
}

Rax Official Drivers

  • driver-dom
  • driver-weex
  • driver-webgl
  • driver-worker

Rax Renderers

Developer Tools

  • React Developer Tools: Allow you inspect and modify the state of your Rax components at runtime in Chrome Developer Tools.

React Developer Tools

Redux DevTools extension

Contributing

Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our guidelines for contributing.

Development Workflow

After cloning rax, run npm install to fetch its dependencies.
Run npm run setup link and bootstrap project before development. Then, you can run several commands:

  • npm run lint checks the code style.
  • npm test runs the complete test suite.
  • npm test -- --watch runs an interactive test watcher.
  • npm test <pattern> runs tests with matching filenames.
  • npm run build creates lib and dist folder with all the packages.
  • npm start start local server with examples folder.

Core Team


@yuanyan

Core


@imsobear

Development


@yacheng

Universals & Components


@boiawang

Loaders & Plugins


@wssgcg1213

DSL Runtimes & Loaders

Users


⬆ back to top

About

[ 🚧Work In Progress v1.0] The fastest way to build cross-container application.

License:Other


Languages

Language:JavaScript 94.7%Language:HTML 5.3%Language:Shell 0.1%Language:CSS 0.0%