美文网首页
仿element组件封装【复习组件间值传递】

仿element组件封装【复习组件间值传递】

作者: Do_Du | 来源:发表于2019-11-06 10:55 被阅读0次

一、prop知识点复习[父组件传值给子组件]

props 是父组件传递值给子组件,子组件接收 Props Down

因为props是单向传递,变量num=5从父组件传递给子组件,子组件想要修改num的值是不能直接修改的,需要通过emit触发父组件的方法传递值回父组件

props写法:

1、props 写成数组格式

子组件接收一个参数

props: ['initialCounter']

子组件接收一个以上参数

props: ['initialCounter','propC']

2、props 写成json格式,常用

 props: {
    initialCounter: {
      type: String, // 类型
      required: true, // 是否是必填,否为false
      default: 'abc' // 默认值
  },
  propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
   },
  propC: {
      type: String,
      required: true
  },
}
用prop传递一个初始值

data 定义新变量存

props: ['initialCounter'],
data: function () {
 return {
   counter: this.initialCounter
 }
}

或者使用计算属性取默认值

props: ['initialCounter'],
data: function () {
 return {
 }
},
computed:{
 counter(){
   return this..initialCounter
 }
}
用prop 以一种原始的值传入且需要进行转换
props: ['size'],
computed: {
 normalizedSize: function () {
   return this.size.trim().toLowerCase()
 }
}

二、$emit 子组件传值给父组件

需要改变通过prop传给子组件的参数,在子组件中用$emit触发父组件的自定义事件
如:父组件传num给子组件:<tab num="5"></tab>
子组件接收:props: [num]
子组件自定义事件给父组件改变num初始值:<button @click='change('6')'>

change(data){ this.$emit('changeNum', data)}

父组件触发事件改变值<tab num="5" @changeNum = 'changeClick'></tab>

changeClick(data){ this.num = data}

三、v-model 在子组件和父组件通信

父组件通过v-model双向绑定num值传递给子组件<tab v-model="num" ></tab>
子组件默认接收参数value: props: [value]
子组件默认传递自定义事件input:this.$emit('input', data)

<template>
  <div class="app-container">
    <InputNumber v-model="parentNum" @input="change" /> // v-model 传值,@input接收事件,change重新定义的新方法名
  </div>
</template>

<script>
import InputNumber from './InputNumber'

export default {
  name: 'UserManager',
  components: {
    InputNumber
  },
  data() {
    return {
      parentNum: 5
    }
  },
  methods: {
    change(data) {
      this.parentNum = data
    }
  }
}
</script>

子组件

<template>
  <div class="inputNumber">
    <button @click="change(-1)">-</button>
    <input :value="value" type="text"> // :value="value" 第一个value input的value属性,第二个value是v-model默认专递给子组件的参数
    <button @click="change(1)">+</button>
  </div>
</template>

<script>
export default {
  props: {
    value: {  // 默认接收value参数
      type: Number,
      required: true
    }
  },
  data() {
    return {
    }
  },
  methods: {
    change(data) {
      this.$emit('input', this.value + data) //默认传递input事件给父组件
    }
  }
}

四、应用

1、InputNumber 计数器(父组件和子组件传递值)

父组件:

// 使用子组件 并从父组件传递num变量给子组件,重写子组件传递回来的方法 改变num的值
<InputNumber :num="numParent" @input-change="handleIncrementParent" /> 


<script>
import InputNumber from './InputNumber'   // 引入子组件

export default {
  components: {
    InputNumber
  },
  data() {
    return {
      numParent: 5
    }
  },
  methods: {
    handleIncrementParent(evalue) { // 触发子组件传递回来的方法
      this.numParent = evalue
    }
  }

}
</script>

子组件

<div>
    <button @click="handleIncrement(-1)">-</button>
    <input :value="num" type="text"> // 
    <button @click="handleIncrement(1)">+</button>
  </div>

<script>
export default {
  props: {        // 接收父组件传来的num
    num: {
      type: Number,
      required: true
    }
  },
  data() {
    return {
      // num: 1  // 这里data不能重复定义num,若是需要针对这个num做处理,可以通过computed计算属性
    }
  },
  methods: {
    handleIncrement(count) {
      if (this.num <= 0 && count < 0) {
        this.$emit('input-change', 0)
      } else {
        this.$emit('input-change', this.num + count)
      }
    }
  }

}
</script>

2、Tabs 标签页

应用页面 index(父组件)

  <template>
  <div class="app-container">
    // 步骤4
    <tabs v-model="activeName">
      <tab-panes label="用户管理" name="first">用户管理1</tab-panes>
      <tab-panes label="角色管理" name="second">角色管理2</tab-panes>
    </tabs>
  </div>
</template>

<script>
import tabs from './tab'  // 步骤1
import tabPanes from './tabPanes'

export default {
  name: 'UserManager',
  components: { // 步骤2
    tabs,
    tabPanes
  },
  data() {
    return {
      activeName: 'first' // 步骤3
    }
  },
  created() {
  },
  methods: {
  }
}
</script>

tab子组件(index页面的子组件,tabPanes的父组件)

<template>
  <div class="tab-wrapper">
    <div class="tab-header">
      <span v-for="item in tabPanes" :key="item.name" :class="{active: activeName == item.name}" @click="tabClick(item)">{{ item.label }}</span>
    </div>
    <div class="tab-body">
      <slot />
    </div>
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      tabPanes: []
    }
  },
  computed: {
    activeName() {
      return this.value
    }
  },
  mounted() {
    this.tabPanes = this.$children // 这里的children为tab-panes
  },
  methods: {
    tabClick(tab) {
      this.$emit('input', tab.name)
    }
  }
}
</script>

tabPanes子组件

<template>
  <div v-show="name == $parent.activeName"><slot /></div>
</template>

<script>
export default {
  props: {
    label: {
      type: String,
      required: true
    },
    name: {
      type: String,
      required: true
    }
  },
  data() {
    return {
    }
  },
  mounted() {
    console.log(this.$parent) // 这里的parent为tab组件
  }
}
</script>

相关文章

网友评论

      本文标题:仿element组件封装【复习组件间值传递】

      本文链接:https://www.haomeiwen.com/subject/elcbvctx.html