diff --git a/CHANGE.md b/CHANGE.md
index 6f5d756..a36640b 100644
--- a/CHANGE.md
+++ b/CHANGE.md
@@ -38,4 +38,6 @@ DropdownItem key 改为 name, Dropdown 的 visible 要使用 @on-visible-change 
 DropdownItem 里,this.$parent.$parent 与1.0 有区别
 ### Menu
 MenuItem 和 Submenu 的 key 改为了 name
-Menu 的 activeKey 改为 activeName,openKeys 改为 openNames
\ No newline at end of file
+Menu 的 activeKey 改为 activeName,openKeys 改为 openNames
+### Cascader
+Caspanel 的 sublist 从 prop -> data
diff --git a/README.md b/README.md
index 94328f2..0e707fa 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@
 - [x] Slider
 - [ ] DatePicker
 - [ ] TimePicker
-- [ ] Cascader
+- [x] Cascader
 - [ ] Transfer
 - [x] InputNumber
 - [x] Rate
diff --git a/examples/app.vue b/examples/app.vue
index a966f99..0f3fa75 100644
--- a/examples/app.vue
+++ b/examples/app.vue
@@ -42,6 +42,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; }
                 <li><router-link to="/breadcrumb">Breadcrumb</router-link></li>
                 <li><router-link to="/menu">Menu</router-link></li>
                 <li><router-link to="/spin">Spin</router-link></li>
+                <li><router-link to="/cascader">Cascader</router-link></li>
             </ul>
         </nav>
         <router-view></router-view>
diff --git a/examples/main.js b/examples/main.js
index cc2ebdb..c3b505e 100644
--- a/examples/main.js
+++ b/examples/main.js
@@ -132,6 +132,10 @@ const router = new VueRouter({
         {
             path: '/spin',
             component: require('./routers/spin.vue')
+        },
+        {
+            path: '/cascader',
+            component: require('./routers/cascader.vue')
         }
     ]
 });
diff --git a/examples/routers/cascader.vue b/examples/routers/cascader.vue
index d8ebc3f..595d367 100644
--- a/examples/routers/cascader.vue
+++ b/examples/routers/cascader.vue
@@ -1,24 +1,85 @@
-<template>
-    {{ text }}
-    <Cascader :data="data" @on-change="handleChange">
-        <a href="javascript:void(0)">选择</a>
-    </Cascader>
+<!--<template>-->
+    <!--<div>-->
+        <!--<Cascader :data="data" v-model="value1"></Cascader>-->
+        <!--{{ value1 }}-->
+        <!--<div @click="c">change</div>-->
+    <!--</div>-->
+<!--</template>-->
+<!--<script>-->
+    <!--export default {-->
+        <!--data () {-->
+            <!--return {-->
+                <!--value1: [],-->
+                <!--data: [{-->
+                    <!--value: 'beijing',-->
+                    <!--label: '北京',-->
+                    <!--children: [-->
+                        <!--{-->
+                            <!--value: 'gugong',-->
+                            <!--label: '故宫'-->
+                        <!--},-->
+                        <!--{-->
+                            <!--value: 'tiantan',-->
+                            <!--label: '天坛'-->
+                        <!--},-->
+                        <!--{-->
+                            <!--value: 'wangfujing',-->
+                            <!--label: '王府井'-->
+                        <!--}-->
+                    <!--]-->
+                <!--}, {-->
+                    <!--value: 'jiangsu',-->
+                    <!--label: '江苏',-->
+                    <!--children: [-->
+                        <!--{-->
+                            <!--value: 'nanjing',-->
+                            <!--label: '南京',-->
+                            <!--children: [-->
+                                <!--{-->
+                                    <!--value: 'fuzimiao',-->
+                                    <!--label: '夫子庙',-->
+                                <!--}-->
+                            <!--]-->
+                        <!--},-->
+                        <!--{-->
+                            <!--value: 'suzhou',-->
+                            <!--label: '苏州',-->
+                            <!--children: [-->
+                                <!--{-->
+                                    <!--value: 'zhuozhengyuan',-->
+                                    <!--label: '拙政园',-->
+                                <!--},-->
+                                <!--{-->
+                                    <!--value: 'shizilin',-->
+                                    <!--label: '狮子林',-->
+                                <!--}-->
+                            <!--]-->
+                        <!--}-->
+                    <!--],-->
+                <!--}]-->
+            <!--}-->
+        <!--},-->
+        <!--methods: {-->
+            <!--c () {-->
+                <!--this.value1 = ['jiangsu', 'suzhou', 'zhuozhengyuan']-->
+            <!--}-->
+        <!--}-->
+    <!--}-->
+<!--</script>-->
+
 
-    <Row>
-        <i-col span="4">
-            Disabled <Switch :checked.sync="disabled"></Switch>
-        </i-col>
-        <i-col span="4">
-            <Cascader :data="data" :value.sync="value1" :disabled="disabled"></Cascader>
-        </i-col>
-    </Row>
+<template>
+    <div>
+        <Cascader :data="data" v-model="value2" change-on-select></Cascader>
+        {{ value2 }}
+        <div @click="c">change</div>
+    </div>
 </template>
 <script>
     export default {
         data () {
             return {
-                disabled: false,
-                text: '未选择',
+                value2: [],
                 data: [{
                     value: 'beijing',
                     label: '北京',
@@ -69,8 +130,8 @@
             }
         },
         methods: {
-            handleChange (value, selectedData) {
-                this.text = selectedData.map(o => o.label).join(', ');
+            c () {
+                this.value2 = ['jiangsu', 'suzhou', 'zhuozhengyuan']
             }
         }
     }
diff --git a/src/components/cascader/cascader.vue b/src/components/cascader/cascader.vue
index 254c30d..9ff66e2 100644
--- a/src/components/cascader/cascader.vue
+++ b/src/components/cascader/cascader.vue
@@ -5,39 +5,43 @@
                 <i-input
                     readonly
                     :disabled="disabled"
-                    :value.sync="displayRender"
+                    v-model="displayRender"
                     :size="size"
                     :placeholder="placeholder"></i-input>
-                <Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.stop="clearSelect"></Icon>
+                <Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSelect"></Icon>
                 <Icon type="arrow-down-b" :class="[prefixCls + '-arrow']"></Icon>
             </slot>
         </div>
-        <Dropdown v-show="visible" transition="slide-up">
-            <div>
-                <Caspanel
-                    v-ref:caspanel
-                    :prefix-cls="prefixCls"
-                    :data.sync="data"
-                    :disabled="disabled"
-                    :change-on-select="changeOnSelect"
-                    :trigger="trigger"></Caspanel>
-            </div>
-        </Dropdown>
+        <transition name="slide-up">
+            <Drop v-show="visible">
+                <div>
+                    <Caspanel
+                        ref="caspanel"
+                        :prefix-cls="prefixCls"
+                        :data="data"
+                        :disabled="disabled"
+                        :change-on-select="changeOnSelect"
+                        :trigger="trigger"></Caspanel>
+                </div>
+            </Drop>
+        </transition>
     </div>
 </template>
 <script>
     import iInput from '../input/input.vue';
-    import Dropdown from '../select/dropdown.vue';
+    import Drop from '../select/dropdown.vue';
     import Icon from '../icon/icon.vue';
     import Caspanel from './caspanel.vue';
     import clickoutside from '../../directives/clickoutside';
     import { oneOf } from '../../utils/assist';
+    import Emitter from '../../mixins/emitter';
 
     const prefixCls = 'ivu-cascader';
 
     export default {
         name: 'Cascader',
-        components: { iInput, Dropdown, Icon, Caspanel },
+        mixins: [ Emitter ],
+        components: { iInput, Drop, Icon, Caspanel },
         directives: { clickoutside },
         props: {
             data: {
@@ -92,7 +96,8 @@
                 visible: false,
                 selected: [],
                 tmpSelected: [],
-                updatingValue: false    // to fix set value in changeOnSelect type
+                updatingValue: false,    // to fix set value in changeOnSelect type
+                currentValue: this.value
             };
         },
         computed: {
@@ -107,7 +112,7 @@
                 ];
             },
             showCloseIcon () {
-                return this.value && this.value.length && this.clearable;
+                return this.currentValue && this.currentValue.length && this.clearable;
             },
             displayRender () {
                 let label = [];
@@ -120,11 +125,12 @@
         },
         methods: {
             clearSelect () {
-                const oldVal = JSON.stringify(this.value);
-                this.value = this.selected = this.tmpSelected = [];
+                const oldVal = JSON.stringify(this.currentValue);
+                this.currentValue = this.selected = this.tmpSelected = [];
                 this.handleClose();
-                this.emitValue(this.value, oldVal);
-                this.$broadcast('on-clear');
+                this.emitValue(this.currentValue, oldVal);
+//                this.$broadcast('on-clear');
+                this.broadcast('Caspanel', 'on-clear');
             },
             handleClose () {
                 this.visible = false;
@@ -139,8 +145,8 @@
             },
             onFocus () {
                 this.visible = true;
-                if (!this.value.length) {
-                    this.$broadcast('on-clear');
+                if (!this.currentValue.length) {
+                    this.broadcast('Caspanel', 'on-clear');
                 }
             },
             updateResult (result) {
@@ -148,25 +154,30 @@
             },
             updateSelected (init = false) {
                 if (!this.changeOnSelect || init) {
-                    this.$broadcast('on-find-selected', this.value);
+                    this.broadcast('Caspanel', 'on-find-selected', {
+                        value: this.currentValue
+                    });
                 }
             },
             emitValue (val, oldVal) {
                 if (JSON.stringify(val) !== oldVal) {
-                    this.$emit('on-change', this.value, JSON.parse(JSON.stringify(this.selected)));
-                    this.$dispatch('on-form-change', this.value, JSON.parse(JSON.stringify(this.selected)));
+                    this.$emit('on-change', this.currentValue, JSON.parse(JSON.stringify(this.selected)));
+                    // todo 事件
+//                    this.$dispatch('on-form-change', this.currentValue, JSON.parse(JSON.stringify(this.selected)));
                 }
             }
         },
-        ready () {
+        mounted () {
             this.updateSelected(true);
-        },
-        events: {
-            // lastValue: is click the final val
-            // fromInit: is this emit from update value
-            'on-result-change' (lastValue, changeOnSelect, fromInit) {
+            this.$on('on-result-change', (params) => {
+                // lastValue: is click the final val
+                // fromInit: is this emit from update value
+                const lastValue = params.lastValue;
+                const changeOnSelect = params.changeOnSelect;
+                const fromInit = params.fromInit;
+
                 if (lastValue || changeOnSelect) {
-                    const oldVal = JSON.stringify(this.value);
+                    const oldVal = JSON.stringify(this.currentValue);
                     this.selected = this.tmpSelected;
 
                     let newVal = [];
@@ -176,30 +187,37 @@
 
                     if (!fromInit) {
                         this.updatingValue = true;
-                        this.value = newVal;
-                        this.emitValue(this.value, oldVal);
+                        this.currentValue = newVal;
+                        this.emitValue(this.currentValue, oldVal);
                     }
                 }
                 if (lastValue && !fromInit) {
                     this.handleClose();
                 }
-            },
-            'on-form-blur' () {
-                return false;
-            },
-            'on-form-change' () {
-                return false;
-            }
+            });
         },
+        // todo 事件 这是因为内部的input会触发,应该组织
+//        events: {
+//            'on-form-blur' () {
+//                return false;
+//            },
+//            'on-form-change' () {
+//                return false;
+//            }
+//        },
         watch: {
             visible (val) {
                 if (val) {
-                    if (this.value.length) {
+                    if (this.currentValue.length) {
                         this.updateSelected();
                     }
                 }
             },
-            value () {
+            value (val) {
+                this.currentValue = val;
+            },
+            currentValue () {
+                this.$emit('input', this.currentValue);
                 if (this.updatingValue) {
                     this.updatingValue = false;
                     return;
diff --git a/src/components/cascader/casitem.vue b/src/components/cascader/casitem.vue
index a0171b2..2f68ce9 100644
--- a/src/components/cascader/casitem.vue
+++ b/src/components/cascader/casitem.vue
@@ -3,6 +3,7 @@
 </template>
 <script>
     export default {
+        name: 'Casitem',
         props: {
             data: Object,
             prefixCls: String,
diff --git a/src/components/cascader/caspanel.vue b/src/components/cascader/caspanel.vue
index bae638c..804092f 100644
--- a/src/components/cascader/caspanel.vue
+++ b/src/components/cascader/caspanel.vue
@@ -1,19 +1,23 @@
 <template>
-    <ul v-if="data && data.length" :class="[prefixCls + '-menu']">
-        <Casitem
-            v-for="item in data"
-            :prefix-cls="prefixCls"
-            :data.sync="item"
-            :tmp-item="tmpItem"
-            @click.stop="handleClickItem(item)"
-            @mouseenter.stop="handleHoverItem(item)"></Casitem>
-    </ul><Caspanel v-if="sublist && sublist.length" :prefix-cls="prefixCls" :data.sync="sublist" :disabled="disabled" :trigger="trigger" :change-on-select="changeOnSelect"></Caspanel>
+    <span>
+        <ul v-if="data && data.length" :class="[prefixCls + '-menu']">
+            <Casitem
+                v-for="item in data"
+                :prefix-cls="prefixCls"
+                :data="item"
+                :tmp-item="tmpItem"
+                @click.native.stop="handleClickItem(item)"
+                @mouseenter.native.stop="handleHoverItem(item)"></Casitem>
+        </ul><Caspanel v-if="sublist && sublist.length" :prefix-cls="prefixCls" :data="sublist" :disabled="disabled" :trigger="trigger" :change-on-select="changeOnSelect"></Caspanel>
+    </span>
 </template>
 <script>
     import Casitem from './casitem.vue';
+    import Emitter from '../../mixins/emitter';
 
     export default {
         name: 'Caspanel',
+        mixins: [ Emitter ],
         components: { Casitem },
         props: {
             data: {
@@ -22,12 +26,6 @@
                     return [];
                 }
             },
-            sublist: {
-                type: Array,
-                default () {
-                    return [];
-                }
-            },
             disabled: Boolean,
             changeOnSelect: Boolean,
             trigger: String,
@@ -36,9 +34,15 @@
         data () {
             return {
                 tmpItem: {},
-                result: []
+                result: [],
+                sublist: []
             };
         },
+        watch: {
+            data () {
+                this.sublist = [];
+            }
+        },
         methods: {
             handleClickItem (item) {
                 if (this.trigger !== 'click' && item.children) return;
@@ -58,10 +62,20 @@
 
                 if (item.children && item.children.length){
                     this.sublist = item.children;
-                    this.$dispatch('on-result-change', false, this.changeOnSelect, fromInit);
+//                    this.$dispatch('on-result-change', false, this.changeOnSelect, fromInit);
+                    this.dispatch('Cascader', 'on-result-change', {
+                        lastValue: false,
+                        changeOnSelect: this.changeOnSelect,
+                        fromInit: fromInit
+                    });
                 } else {
                     this.sublist = [];
-                    this.$dispatch('on-result-change', true, this.changeOnSelect, fromInit);
+//                    this.$dispatch('on-result-change', true, this.changeOnSelect, fromInit);
+                    this.dispatch('Cascader', 'on-result-change', {
+                        lastValue: true,
+                        changeOnSelect: this.changeOnSelect,
+                        fromInit: fromInit
+                    });
                 }
             },
             updateResult (item) {
@@ -84,13 +98,9 @@
                 }
             }
         },
-        watch: {
-            data () {
-                this.sublist = [];
-            }
-        },
-        events: {
-            'on-find-selected' (val) {
+        mounted () {
+            this.$on('on-find-selected', (params) => {
+                const val = params.value;
                 let value = [...val];
                 for (let i = 0; i < value.length; i++) {
                     for (let j = 0; j < this.data.length; j++) {
@@ -98,17 +108,19 @@
                             this.handleTriggerItem(this.data[j], true);
                             value.splice(0, 1);
                             this.$nextTick(() => {
-                                this.$broadcast('on-find-selected', value);
+                                this.broadcast('Caspanel', 'on-find-selected', {
+                                    value: value
+                                });
                             });
                             return false;
                         }
                     }
                 }
-            },
-            'on-clear' () {
+            });
+            this.$on('on-clear', () => {
                 this.sublist = [];
                 this.tmpItem = {};
-            }
+            });
         }
     };
 </script>
diff --git a/src/components/spin/spin.vue b/src/components/spin/spin.vue
index b4e8cc3..25a619d 100644
--- a/src/components/spin/spin.vue
+++ b/src/components/spin/spin.vue
@@ -14,6 +14,7 @@
     const prefixCls = 'ivu-spin';
 
     export default {
+        name: 'Spin',
         props: {
             size: {
                 validator (value) {
diff --git a/src/index.js b/src/index.js
index 8b9373f..eec82f8 100644
--- a/src/index.js
+++ b/src/index.js
@@ -9,7 +9,7 @@ import Breadcrumb from './components/breadcrumb';
 import Button from './components/button';
 import Card from './components/card';
 import Carousel from './components/carousel';
-// import Cascader from './components/cascader';
+import Cascader from './components/cascader';
 import Checkbox from './components/checkbox';
 import Circle from './components/circle';
 import Collapse from './components/collapse';
@@ -59,7 +59,7 @@ const iview = {
     Card,
     Carousel,
     CarouselItem: Carousel.Item,
-    // Cascader,
+    Cascader,
     Checkbox,
     CheckboxGroup: Checkbox.Group,
     iCircle: Circle,
diff --git a/src/mixins/emitter.js b/src/mixins/emitter.js
index 422f5ac..e4bac47 100755
--- a/src/mixins/emitter.js
+++ b/src/mixins/emitter.js
@@ -5,6 +5,7 @@ function broadcast(componentName, eventName, params) {
         if (name === componentName) {
             child.$emit.apply(child, [eventName].concat(params));
         } else {
+            // todo 如果 params 是空数组,接收到的会是 undefined
             broadcast.apply(child, [componentName, eventName].concat([params]));
         }
     });
--
libgit2 0.21.4