Coder Social home page Coder Social logo

vuejs-redux's Introduction

vuejs-redux

npm version Build Status GitHub contributors Say Thanks!

Description

Flexible binding between Vue and Redux, allowing use of multiple stores. It works, in the same way, like render props does in React. It uses Scoped Slot - read my article about it.

Note: The previous version was using Higher Order Components (HOC); this version uses Scoped slots instead. No more magic with the connect methods. Everything is explicit which will prevent props collision and an ugly trick with the render function.

Why you should use it:

  • Just 45 lines of code.
  • No dependencies at all
  • Easy to read, understand, and extend.
  • Same API as react-redux.
  • Combine multiple Providers to be populated by multiple sources.
  • No hard coded dependencies between 'Vue' and the store, so more composable.
  • Doesn't polluate data, so you can use the power of the functional component
  • Debuggable in the Vue devtool browser extension.
  • Elegant JSX syntax.

Table of Contents

Created by gh-md-toc

Install

npm install --save vuejs-redux

Counter example

Let's build a counter app. The full code can be found in the example/ directory.

Start with a reducer:

export function counter(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    case 'RESET':
      return 0
    default:
      return state
  }
}

Create the action creators in order to update our state:

export function increment() {
  return { type: 'INCREMENT' }
}

export function decrement() {
  return { type: 'DECREMENT' }
}

export function reset() {
  return { type: 'RESET' }
}

We can now create the CounterProvider component. It acts as a Provider for our CounterComponent:

<template>
  <Provider
    :mapDispatchToProps="mapDispatchToProps"
    :mapStateToProps="mapStateToProps"
    :store="store"
  >
    <template #default="{ counterValue, actions }">
      <!-- the provider calls the default slot with the result of mapStateToProps and mapDispatchToProps -->
      <Counter :counterValue="counterValue" :actions="actions" :title="title" />
      <!-- explicitly pass other props (ex: title) -->
    </template>
  </Provider>
</template>

<script>
import Provider from 'vuejs-redux'

import { createStore, bindActionCreators } from 'redux'
import { counter } from '../Reducers/Counter'
import * as Actions from '../Actions'

import Counter from './Counter.vue'

export default {
  methods: {
    mapStateToProps(state) {
      return { counterValue: state }
    },

    mapDispatchToProps(dispatch) {
      return { actions: bindActionCreators(Actions, dispatch) }
    },
  },

  components: {
    Counter,
    Provider,
  },

  data: () => ({
    store: createStore(counter),
    title: 'Counter using vuejs-redux',
  }),
}
</script>

And finally our Counter component:

<template functional>
  <!-- we can use functional component -->
  <div>
    <h1>Counter using vuejs-redux</h1>
    <div>{{ counterValue }}</div>
    <button @click="actions.increment()">increment</button>
    <button @click="actions.decrement()">decrement</button>
    <button @click="actions.reset()">reset</button>
  </div>
</template>

<script>
export default {
  props: ['actions', 'counterValue'],
}
</script>

The Counter component is not aware that we are using redux.

If you use JSX, you can use the same syntax as React render props:

render(h) {
    return (
      <Provider mapDispatchToProps={this.mapDispatchToProps} mapStateToProps={this.mapStateToProps} store={this.store}>
        {({actions, counterValue}) => (
          <Counter counterValue={counterValue} actions={actions} title={this.title} />
        )}
      </Provider>
    );
  },

Multiple stores

You can combine multiple store if needed, use the Provider component various times. You can obviously create an helper component or whatever to compose this.

<template>
  <Provider
    :store=storeOne
    :mapStateToProps=mapStateToPropsOne
    :mapDispatchToProps=mapDispatchToPropsOne>
      <template #default="{ myStateOne, myActionOne }">
        <!-- Use our second provider -->
        <Provider
          :store=storeTwo
          :mapStateToProps=mapStateToPropsTwo
          :mapDispatchToProps=mapDispatchToPropsTwo>
          <template #default="{ myStateTwo, myActionTwo }">
            <!-- render our component here -->
            <Child :stateOne=myStateOne :stateTwo=myStateTwo />
          </template>
        </Provider>
      </template>
    </Provider
</template>

Avoid passing the store to every <Provider ...>

Importing the store and passing it to every Provider can be a pain point. Hopefully, we can create a custom provider that receive mapStateToProps and mapDispatchToProps as props, imports the store, and call the vuejs-redux provider with the right parameters.

Here is an example:

CustomProvider.vue

<template>
  <Provider
    :mapDispatchToProps="mapDispatchToProps"
    :mapStateToProps="mapStateToProps"
    :store="store"
  >
    <template #default="props">
      <!--Retrieve the data from the provider -->
      <slot v-bind="props"></slot>
      <!-- forward the data to the scoped-slot -->
    </template>
  </Provider>
</template>

<script>
import store from '../configure-store'
import Provider from 'vuejs-redux'

export default {
  props: ['mapDispatchToProps', 'mapStateToProps'],

  components: {
    Provider,
  },

  data: () => ({
    store,
  }),
}
</script>

Checkout the working example

Running the examples locally

Sometimes, the examples in the repo are more up-to-date than the example in codesandbox. You can open an issue if you find a broken codesandbox example.

To run the example locally, you need to switch to the example directory:

cd ./examples/counter

Install the dependencies with:

npm install # (or yarn)

Either build the example and serve the dist directory or start the dev mode (with hot reloading)

# Start the development mode
npm start

# Build
npm run build

Testing

Unit testing is done with jest. To run the test:

npm test

Rematch

This plugin is compatible with rematch: live example

Live examples

CONTRIBUTING

Feel free to create issues or pull requests if needed.

vuejs-redux's People

Contributors

ablank-te avatar danfoy avatar deerawan avatar dependabot[bot] avatar khrystuk avatar marceloalves avatar muhammadhasham23 avatar nogrtl avatar pasha00786 avatar siddarthvijay avatar sisou avatar titouancreach avatar vvscode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vuejs-redux's Issues

Rewrite the readme

The readme is bad written, contains typo, that would be good to rewrite it or correct it

Version 3 discussion

I've some idea to make this plugin evolve in a near future.

Restore the connect function

Why

We can export only one component to the .vue files (due to the templates). To connect a component, we need to create 2 .vue. One is the provider, the other is the dumb component. It can be useful to use the connect function for trivial connected components.

Drawback

The HOCs in Vue can lead to some bugs and the connect function would be in alpha version.

Breaking change

The connect function would be exported as a named export. The default export won't change to avoid any breaking change

Add a Provider and HOC to connect rematch

Why

I really like rematch and how they abstracted redux in the right way. I would imagine a Provider that is easier to connect with the dumb component.

How do you see the integration with rematch ?
Do you have any issues about this ?

Components 'watch' not firing when props change in store.

I think this is because of how redux replaces the whole store each time there is an update, probably knocking out the vue.js getter + setter bindings on the way.

I have a component which passes the prop down to a child, which must watch the prop change and perform some action. However when the prop changes in the parent, the child does not get the new prop.

Is there any way around this? Such as not clobbering the vue getter + setter from object?

store.subscribe() is faster than vuejs re-rendering and cause bad props.

Imagine a store

{
  foo: {
    byId: {0: 'foo'},
    allIds: [0]
  }
}

and the component Foo:

<OtherComponent>
  {getFooAllIds().map(fooId => (
    <Foo id={fooid} />
  )}
</OtherComponent>

If a "foo" is deleted from the store, <Foo id={0} /> is still here until the rerendering. It cause this component to be wrong during some milliseconds.

Add a section in a readme

Maybe we need a section in the readme to explain how to run the example.
It's:

  • cd example/xxxx
  • npm install (or yarn install)
  • npm run dev / npm run build

Performance

this.state = this.mapStateToProps(this.store.getState());

Here we change the state of our state, that cause a rerendering of all our components that depends of at least one store of the store. As react-redux, I should perform a diff to know if I need to mutate the state or not.

Why don't support connect?

I think in vue's pattern, we can use provide/inject to support Provider and Connect Components, and then It will be more redux-liked?

For example:

Provider๏ผš

<script>
export default {
  name: 'Provider',

  props: {
    store: {
      required: true,
      type: Object,
      validator: function (store) {
        if (!store.dispatch && !store.subscribe && !store.getState) {
          throw new Error('[revux] - store provided is not a valid redux store')
        }
        return true
      }
    }
  },

  provide () { // Provided properties are also not reactive
    return {
      $$store: this.store
    }
  },

  render (h) {
    if (this.$slots.default.length > 1) {
      return h('div', this.$slots.default)
    }
    return this.$slots.default[0]
  }
}
</script>

Connect๏ผš

<script>
export default {
  name: 'Connect',

  props: {
    mapDispatchToProps: {
      required: false,
      default: () => ({}),
      type: Function
    },

    mapStateToProps: {
      required: false,
      default: () => ({}),
      type: Function
    }
  },

  inject: ['$$store'],

  created () {
    this._unsubscribe = this.$$store.subscribe(() => {
      this.$forceUpdate() // I think there's no need for the Data Methods
    })
  },

  destroyed () {
    this._unsubscribe()
  },

  render () {
    const {
      $$store,
      $scopedSlots,
      mapStateToProps,
      mapDispatchToProps
    } = this
    const nodes = $scopedSlots.default({
      ...mapDispatchToProps($$store.dispatch),
      ...mapStateToProps($$store.getState())
    })
    if (Array.isArray(nodes)) {
      return nodes[0]
    } else {
      return nodes
    }
  }
}
</script>

and the use case may like this

App.vue๏ผš

<template>
  <Provider id="app" :store="store">
    <router-view/>
  </Provider>
</template>

<script>
  import Provider from './components/Provider.vue'
  import store from "./rematch"
  export default {
    name: 'app',
    components: {
      Provider
    },
    data: () => ({
      store
    })
  }
</script>

Counter.vue๏ผš

<template>
  <Connect
    :mapStateToProps="mapStateToProps"
    :mapDispatchToProps="mapDispatchToProps">
    <Count slot-scope="props"
      :count="props.count"
      :increment="props.increment"
      :incrementAsync="props.incrementAsync" />
  </Connect>
</template>

<script>
import Connect from '../components/Connect.vue'
import Count from "../components/Count.vue"

const mapStateToProps = state => ({
  count: state.counter
})

const mapDispatchToProps = dispatch => ({
  increment: dispatch.counter.increment,
  incrementAsync: dispatch.counter.incrementAsync
})

export default {
  components: {
    Connect,
    Count
  },

  methods: {
    mapStateToProps,
    mapDispatchToProps
  }
}
</script>

inspired: https://github.com/edvincandon/revux
related: https://vuejs.org/v2/guide/components-edge-cases.html#Dependency-Injection
demo: https://github.com/zhangchen91/vue-rematch-immer

Add prettier

That would be cool if we add a prettierrc file, add a command to format in the package.json, and add prettier in the dev dependencies

New name

I've not convinced with vuejs-redux as a good name for this project. I've choosen this name because I had no other idea. I'm also looking for a logo (simple SVG stuff). I'm open to any proposition !

What side effect can we have with NPM ?

replace npm run dev to npm run start

create react app and many other project use npm start to start the dev server, maybe we can change the name script in the example to match this

ctx is not defined in data(ctx) function

Hello,

I'm using the provider, but not in a webpack-built project, but without the build step. Thus I have this template in my HTML:

<div class="modal-body" id="vue-contact-list">
    <redux-provider :map-state-to-props="mapStateToProps" :map-dispatch-to-props="mapDispatchToProps" :store="store">
        <template slot-scope="{contacts, actions}">
            <contact-list :contacts="contacts" :actions="actions" ref="contactList"></contact-list>
        </template>
    </redux-provider>
</div>

The #vue-contact-list is the mounting point.

Now, when I used your provider component, it told me that Cannot read property 'store' of undefined at https://github.com/titouancreach/vuejs-redux/blob/master/index.js#L23.

Thus I changed data to be

  data() {
    return {
      state: this.store.getState(),
    }
  }

instead.

It works now, but just wanted to let you know, that I have no idea where the ctx comes from. I ran the tests in this repo and it worked, but not in my code :P

mapDispatchToProps is not updated inside the provider

when you use this pattern:

const mapDispatchToProps = myProp => dispatch => ({
  myFunction: .....
})


export default {
  props: ['myProp'],

  render() {
    return (
      <Provider store={store} mapDispatchToProps={mapDispatchToProps(this.myProp)}>
        {({myFunction}) => (
          <Child myFunction={myFunction} />
        )}
     </Provider>
  }
}

Provider store the function mapDispatchToProps(this.myProp) in its state. Since there is no watcher, even if the provider update myProp, mapDispatchToProps is never recalculated inside the Provider.

We don't even need to store mapDispatchToProps. We can direclty call the prop mapDispatchToProps. In this way, if the prop change in the provider, the Provider will be updated with the good function.

Remove formatting notices from README.md

The part

If you change some code, don't forget to run:

npm run format
before submitting a pull request.

is non-actual any more due to

  • precommit hook
  • TravisCI integration

pass slots to child component

For now, I can have the things to work with an ugly:

scopedSlots: { default: () => this.$slots.default }

But I need that working for every slots.

  • Pass every slot to the child
  • Add unit test for default slot
  • Add unit test for multiple scoped slots
  • Test in composing multiple store

Add linter

Since I'm the only maintainer, I can delay this issue.

update dev dependencies

The devDependencies are not up to date, we probably need to do a npm upgrade and check if the test and build don't break

mutation should not be allowed

when I do a JavaScript map in the mapStateToProp Function it changes the original object in the redux store, bad bad bad...

I have something like this

`mapStateToProps(state) {
// map userdetails to each post

            const userList = state.users.items;        
            const posts =  JSON.parse(JSON.stringify(state.posts.items)); // if I don't do JSON trick it will cause an infinite circular loop ==> then my browser crashes
            const postsWithUserDetails = posts.map((x) => {
                //console.log('post'); 
                x.user_details = userList[x.user] ?  userList[x.user] : userList[-1];

                if(x.comments.length > 0) { 

                    const comments = x.comments.map((y) => {
                        //console.log('comment');
                        y.user_details = userList[y.user] ? userList[y.user] : userList[-1];
                        
                        return y; 
                    });  
                    x.comments = comments; 
                }

                return x; 
            });

            //   
            console.log('postsWithUserDetails', postsWithUserDetails); 
            
            return { 
                posts: postsWithUserDetails, 
            }`

Is there a better way for doing this ?

Usage of methods or actions?

When using vuejs-redux which is more interesting or the right way to do it;

  1. having only mapStateToProps and mapDispatchToProps in the 'methods' object, and exporting all my other methods within mapDispatchToProps?

  2. using a mix of functions within 'methods'

    export default { 
    
     data: () => ({ 
         store: store,
     }),
     methods: { 
         onUpdateEditable() {
             console.log('onUpdateEditable  in methods?? '); // here ?
         },
         mapStateToProps(state) { 
             return {
                 currentUser: state.currentUser,
                 newPost: state.postCrud
             } 
         },
         mapDispatchToProps(dispatch) {   
             return {  
                 onUpdateEditable(a,b,c) {
                     console.log('onUpdateEditable in redux actions??');  // or here??
                     console.log(a);
                     console.log(b); 
                     console.log(c); 
                 },
                 actions: bindActionCreators(PostActions, dispatch)
             }
         }
     },
     components: {
         Provider,
         Editable
      }
    
    }
    

The template part

<template>
 <Provider :mapDispatchToProps="mapDispatchToProps" :mapStateToProps="mapStateToProps" :store="store">
    <template slot-scope="{newPost, currentUser, actions, onUpdateEditable}"> 

           <Editable :content="newPost.item.message" :onUpdateEditable="onUpdateEditable"></Editable>
                        
    </template>
</Provider>

problem store init

Hi,

i want to use vuejs + redux + redux-observable.

i have some trouble to add store on the beginning and
to propagate the store to other subs pages/components.

I have another problem with combining 2 reducers.

composition of my project :

  • main.js
  • App.vue
  • provider_sample.vue
  • sample.vue

main.js

import Vue          from 'vue'
import Vuetify      from 'vuetify'
import VueRouter    from 'vue-router'

import App             from './App.vue'

import reduxobservablesample from './provider_sample.vue'

Vue.use(Vuetify);
Vue.use(VueRouter);

const routes = [
    { path: '/reduxobservablesample', component: reduxobservablesample }
]

const router = new VueRouter({
    routes
})

import { createEpicMiddleware }         from 'redux-observable';
import { createStore, applyMiddleware } from 'redux';
import { combineEpics } from 'redux-observable';
import { combineReducers } from 'redux';
import { rootEpicSample }    from './components/module_sample/root'; 
import { rootReducerSample } from './components/module_sample/root'; 


const rootEpic = combineEpics(
    rootEpicSample
    );

const rootReducer = combineReducers({
        rootReducerSample
});

const epicMiddleware = createEpicMiddleware();

const middlewareChoice = applyMiddleware(epicMiddleware)


const store = createStore(
    rootReducer,
    middlewareChoice
);
epicMiddleware.run(rootEpic);

let app = new Vue({
    el: '#app',
    store,
    router,
    components: {App},
    render: h => h(App)
})

App.vue

<template>

<Provider 
    :store="store">
    <v-app dark>
        <v-content>
            <v-container fluid>
                <router-view></router-view>
            </v-container>
        </v-content>
        <v-footer app>&copy; 2018-2019</v-footer>
    </v-app>
</Provider>
</template>

<script>
import Provider         from 'vuejs-redux';

export default {
    components: {
        Provider
    }
}
</script>

<style>
html {
    overflow-y: auto
}
</style>

provider_sample.vue

<template>
    <Provider 
        :mapDispatchToProps="mapDispatchToProps" 
        :mapStateToProps="mapStateToProps"
        :store="store">
        <template slot-scope="{ping_pong, user, actions}"> 
            <Sample :actions="actions" :ping_pong="ping_pong" :user="user" />
        </template>
    </Provider>
</template>

<script>

import { createStore, bindActionCreators } from 'redux';
import Provider from 'vuejs-redux';
import * as Actions  from './ping_actions.js';
import * as Actions2 from './users_actions.js';

import Sample from './sample.vue'
export default{  
    methods: {
        // extract state
        mapStateToProps(state) {
            return { ping_pong: state.ping_pong,
                     user:      state.user  }
        },
        // create binding actions - dispatch 
        mapDispatchToProps(dispatch) {
            return { actions: bindActionCreators( Object.assign({}, Actions, Actions2), dispatch) }
        }
    },
    components: {
        Sample,
        Provider
    }
}
</script>

<style>
</style>

sample.vue

<template>
    <div> 
    <v-btn flat v-on:click="actions.ping()" > PING </v-btn>
    <v-btn flat v-on:click="actions.pong()" > PONG </v-btn>
    <v-textarea auto-grow v-model="ping_pong" 
                readonly=true >
    </v-textarea> 
<br><br>
    <v-btn flat v-on:click="actions.fetchUser()">fetch user</v-btn>
    <v-textarea auto-grow v-model="user" 
                readonly=true>
    </v-textarea>

    </div>
</template>

<script>

export default{
      props: [
          "actions", 
          "ping_pong",
          "user"
          ]
};
</script>

<style>
</style>

the error on chrome

vue.runtime.esm.js:1737 TypeError: Cannot read property 'getState' of undefined
    at s.data (bundle.es.js:29)
    at vue.runtime.esm.js:3413
    at vue.runtime.esm.js:3370
    at Nt (vue.runtime.esm.js:3307)
    at s.e._init (vue.runtime.esm.js:4624)
    at new s (vue.runtime.esm.js:4794)
    at vue.runtime.esm.js:4306
    at init (vue.runtime.esm.js:4127)
    at vue.runtime.esm.js:5604
    at f (vue.runtime.esm.js:5551)
Ke @ vue.runtime.esm.js:1737
Ue @ vue.runtime.esm.js:1728
qe @ vue.runtime.esm.js:1717
(anonymous) @ vue.runtime.esm.js:3415
(anonymous) @ vue.runtime.esm.js:3370
Nt @ vue.runtime.esm.js:3307
e._init @ vue.runtime.esm.js:4624
s @ vue.runtime.esm.js:4794
(anonymous) @ vue.runtime.esm.js:4306
init @ vue.runtime.esm.js:4127
(anonymous) @ vue.runtime.esm.js:5604
f @ vue.runtime.esm.js:5551
(anonymous) @ vue.runtime.esm.js:6087
e._update @ vue.runtime.esm.js:2656
r @ vue.runtime.esm.js:2784
Et.get @ vue.runtime.esm.js:3138
Et @ vue.runtime.esm.js:3127
e @ vue.runtime.esm.js:2791
hn.$mount @ vue.runtime.esm.js:7995
init @ vue.runtime.esm.js:4133
(anonymous) @ vue.runtime.esm.js:5604
f @ vue.runtime.esm.js:5551
(anonymous) @ vue.runtime.esm.js:6126
e._update @ vue.runtime.esm.js:2656
r @ vue.runtime.esm.js:2784
Et.get @ vue.runtime.esm.js:3138
Et @ vue.runtime.esm.js:3127
e @ vue.runtime.esm.js:2791
hn.$mount @ vue.runtime.esm.js:7995
e._init @ vue.runtime.esm.js:4636
hn @ vue.runtime.esm.js:4725
(anonymous) @ index.js:66
n @ bootstrap:19
(anonymous) @ bootstrap:83
(anonymous) @ bootstrap:83
Show 5 more frames
vue.runtime.esm.js:1737 TypeError: Cannot read property 'subscribe' of undefined
   at s.created (bundle.es.js:36) 
vue.runtime.esm.js:1737 TypeError: Cannot read property 'dispatch' of undefined
    at s.render (bundle.es.js:44)

alternative provider_sample.vue

<template>
    <Provider 
        :mapDispatchToProps="mapDispatchToProps" 
        :mapStateToProps="mapStateToProps"
        :store="store">
        <template slot-scope="{ping_pong, user, actions}"> 
            <Sample :actions="actions" :ping_pong="ping_pong" :user="user" />
        </template>
    </Provider>
</template>

<script>

import store            from "./configure_store.js"

import { createStore, bindActionCreators } from 'redux';
import Provider from 'vuejs-redux';
import * as Actions  from './ping_actions.js';
import * as Actions2 from './users_actions.js';

import Sample from './sample.vue'

import { rootReducerSample } from './components/module_sample/root';

export default{  
   data(){
      return { store }
//or
//return { store: createStore(rootReducerSample)}
    },
    methods: {
        // extract state
        mapStateToProps(state) {
            return { ping_pong: state.ping_pong,
                     user:      state.user  }
        },
        // create binding actions - dispatch 
        mapDispatchToProps(dispatch) {
            return { actions: bindActionCreators( Object.assign({}, Actions, Actions2), dispatch) }
        }
    },
    components: {
        Sample,
        Provider
    }
}
</script>

<style>
</style>

configure_store.js

import { createEpicMiddleware }         from 'redux-observable';
import { createStore, applyMiddleware } from 'redux';
import { combineEpics } from 'redux-observable';
import { combineReducers } from 'redux';
import { rootEpicSample }    from './components/module_sample/root'; 
import { rootReducerSample } from './components/module_sample/root'; 


const rootEpic = combineEpics(
    rootEpicSample
    );

const rootReducer = combineReducers({
        rootReducerSample
});

const epicMiddleware = createEpicMiddleware();

const middlewareChoice = applyMiddleware(epicMiddleware)


const store = createStore(
    rootReducer,
    middlewareChoice
);
epicMiddleware.run(rootEpic);

export store

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.