Vue 组件组合:计算器 + 转换器

需求分析:

来看自带计算器的构成,计算器(左) 菜单(中) 转换器(右):

 

Alt text Alt text Alt text



我的构思是:

  • 计算器-数值计算器-单位 分别作为一个单文件组件,包含它俩的父组件名为 计算器
  • 菜单在父组件中。
  • 父组件通过调整菜单,来控制两个子组件的切换。

Alt text


组件内容:

App.vue 调用

<template>
<div>
    <calculator
        :cal-num-options="{'basic':true, 'science':false, 'programmer':false}"
        :cal-unit-options="true">
    </calculator>                    <!--计算器-->
</div>
</template>
<script>
import Calculator from './Calculator.vue' //导入组件

export default{
    components:{Calculator}      //注册组件
}
</script>

 

Calculator.vue 父组件

<template>
    <div id="calculator">

        <select v-model="menu" >...</select>  <!--菜单-->

        <cal-num :menu="menu"> </cal-num>  <!--计算器-数值-->

        <cal-unit :menu="menu"> </cal-unit>  <!--计算器-单位-->

    </div>
</template>
<script>
import CalNum from './CalNum.vue' //导入组件
import CalUnit from './CalUnit.vue'

export default{
    props: { //接受外部参数
        'calNumOptions':{
            type: Object,
            default: {'basic':true, 'science':false, 'programmer': false}
        },
        'calUnitOptions':{
            type: Boolean,
            default: false
        }
    },
    data (){ //自身数据(将要传给子组件)
        return{
            menu: 'basic'
        };
    },
    components:{ //注册组件
        CalNum,
        CalUnit
    }
}
</script>

CalUnit.vue 内容

<template>
    <div>
    ...
    <!----选择列表1---->
    <select @change="selectChange($event,0)">
        <option
          v-for="item in units[menu]" 
          :value="item.ref">
            {{item.text}}
        </option>    <!--根据菜单显示列表内容-->
    </select>
    ...
    </div>
</template>
<script>
    export default{
        props:{
            menu: String //接受菜单参数
        },
        data (){
            return {
                ...
                units:{      //单位
                    volume:[
                        {text:'毫升', ref:1},
                        {text:'升', ref:1000},
                        ...
                    ]
                }
            }
        }
        ...
    }
</script>
 

自检:是否符合开发规范

参考:打造 Vue.js 可复用组件

构成组件
  • props —— 见上图。
  • events —— 子组件没有事件要发给父组件的,故忽略之。
  • slots —— 父组件没有内容需要传到子组件的,故忽略之。理解slot 概念
组件间通信
  • 使用 props
业务无关
  • 命名只表达组件功能
  • 业务数据无关
  • 对外部无依赖
命名空间
  • 命名空间 cal-
上下文无关
  • 没有特别需求且单个组件不至于过重的的前提下,不把一个有独立功能的组件 cal-num cal-unit 拆分成若干个小组件
数据扁平化(不符合)
  • calUnitOptions 类型为 BooleancalNumOptions 类型为 Object
使用自定义事件实现数据的双向绑定(不需要)
使用自定义 watcher 优化 DOM 操作
  • cal-unit 中的 watcher: menu
项目骨架(见上图)

踩坑小记:

  1. <select> 标签绑定数组的元素时,若选项的 value 值相同,则不会触发绑定的数组的改变。
    • 示例代码:
<div id="app">
  <select v-model="myval[0]">
    <option v-for="option in options" :value="option.value">{{option.text}}</option>

  </select>
  myval is: {{myval}}
</div>
</template>
<script>
export default{
    data (){
        return {
            myval:['', ''],
            options: [
                {text: 'A', value: '1'},
                {text: 'B', value: '1'},
                {text: 'C', value: '3'}
            ]
        }
    }
}
</script>
  • 解决:手动在 <select> 标签上绑定 change() 方法,修改数组元素的值

小知识点

  1. import Calculator from './Calculator.vue' ,其中 ./ 表示当前路径下,不加的话找不到的
  2. export default 和 new vue
  3. Vue 中对于命名的调整:驼峰式命名与短横线隔开式命名
  4. 复用子组件时,加载了两个样式表(父和子),并且有冲突。解决:<style> 标签要加上 scoped 属性,会把样式作用域限制在当前组件内。
posted @ 2017-07-13 16:19  ppJuan  阅读(873)  评论(0编辑  收藏  举报