当前位置: 首页 > article >正文

组件上的v-model(数据传递),props验证,自定义事件,计算属性

一.props验证

在封装组件时对外界传递过来的props数据进行合法性校验,从而防止数据不合法问题。

1.基础类型检查

String,Number,Boolean,Array,Object,Date,Function,Symbol

2.多个可能的类型
3.必须项校验
4.属性默认值
5.自定义验证函数
<template>
  <div>父组件</div>
  <DemoSon :msg="msg" :title="title" type="abc"></DemoSon>
</template>
<script>
import DemoSon from './son.vue'
export default {
    name:'demo',
    components:{DemoSon},
    data(){
        return{
            msg:'111',
            title:'abc'
        }
    }
}
</script>

<template>
  <div>子组件</div>
  <p>{{ msg }}{{ title }}</p>
</template>
<script>
export default {
    name:'demo-son',
    props:{
        msg:{
            type:[Number,String],
            required:true,
            default:10
        },
        title:String,
        type:{
            validator(value){
                // true成功,false失败
                return ['success','warning','danger'].indexOf(value)!==-1
            }
        }
    }
}
</script>

二.计算属性computed

计算属性本质上是一个function函数,可以监听data中数据的变化,并return一个计算后的值,供组件渲染dom时使用。

计算属性会缓存计算的结果,只有在计算属性的依赖项发生变化时,才会重新计算。

计算属性只能当作普通数据项使用,不能当作方法调用(不能使用括号调用)。

<template>
    <div>
        <input type="text" v-model.number="num">
    </div>
    <div>{{ plus }}</div>
</template>
  <script>
  export default {
      name:'demo',
      data(){
          return{
              num:111
          }
      },
      computed:{
        plus(){
           return  this.num*2
        }
      }
  }
  </script>
<template>
  <div>
    <table border>
      <tr><td class="goodState">状态</td>
          <td class="goodId">#</td>
          <td class="goodName">名称</td>
          <td class="goodPrice">单价</td>
          <td class="goodNum">数量</td>
          <td class="goodTime">价格</td>
          <td class="goodAction">操作</td>
      </tr>
      <tr v-for="(item,index) in goods.data" :key="item.id">
          <td class="goodState">
              <input type="checkbox" v-model="item.state" :id="item.id">
              <label :for="item.id">{{item.state===true?"上架":"下架"}}</label>
          </td>
          <td class="goodId">{{index+1}}</td>
          <td class="goodName">{{item.name}}</td>
          <td class="goodNum">{{item.price}}</td>
          <td class="goodNum">{{item.num}}</td>
          <td class="goodTime">{{item.num*item.price}}</td>
          <td class="goodAction"><b @click="addFn(item.id,item.num)">+</b><b @click="minusFn(item.id,item.num)">-</b></td>
      </tr>
      <tr>
          <td>总数:{{ number }}</td>
          <td>总计:{{ total }}</td>
      </tr>
    </table>
  </div>
</template>
  <script setup>
import { ref,reactive, computed } from "vue"
const goods=reactive({data:[{
         id:'1',
         name:'苹果',
         state:true,
         price:2,
         num:0,
         time:'2020-11-03 11:00:00'
     },
     {
         id:'2',
         name:'梨',
         state:true,
         price:2,
         num:0,
         time:'2020-11-03 11:00:00'
     },
     {
         id:'3',
         name:'香蕉',
         state:true,
         price:2,
         num:0,
         time:'2020-11-03 11:00:00'
     }
    ]
})
const minusFn=(id,num)=>{
    if(num>0){
    for(let i=0;i<goods.data.length;i++){
        if(goods.data[i].id===id){
            goods.data[i].num= num-1
        }
    }
}
}
const addFn=(id,num)=>{
    for(let i=0;i<goods.data.length;i++){
        if(goods.data[i].id===id){
            goods.data[i].num= num+1
        }
    }
}
const number = computed(()=>{
    let n=0;
    goods.data.forEach((item)=>{
        if(item.state){
            n+=item.num
        }
    })
    return n;
})
const total = computed(()=>{
    let sum=0;
    goods.data.forEach((item)=>{
        if(item.state){
            sum+=item.num*item.price
        }
    })
    return sum;
})
  </script>
  <style scoped lang="scss">
  td{
    width: 200px;
    height: 40px;
  }
  b{
    margin-right: 20px;
  }
</style>

三.自定义事件

1.声明自定义事件
2.触发自定义事件
3.监听自定义事件
<template>
  <div class="card">
    {{ count }}
    <Son @changeCount="changeCount"></Son>
  </div>
</template>
<script >
import Son from './son.vue'
export default{
  name:'index',
  components: {
    Son
  },
  data(){
    return{
      count:0
    }
  },
  methods:{
    changeCount(str){
      this.count = str
    }
  }
}
</script>

<template>
  <button type="button" @click="clickFn">按钮</button>
</template>
<script>
export default{
  name:'son',
  emits:['changeCount'],
  methods:{
    clickFn(){
      this.$emit('changeCount',1)
    }
  }
}
</script>
<template>
  <div class="card">
    {{ count }}
    <Son @changeCount="changeCount"></Son>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import Son from './son.vue'
const count = ref(0)
const changeCount = (str)=>{
  count.value = str
}
</script>

<template>
  <button type="button" @click="clickFn">按钮</button>
</template>
<script setup>
const emit = defineEmits('changeCount')
const clickFn = () => {
  emit('changeCount',1)
}
</script>

四.组件上v-model

1.父传子

a.父组件通过v-bind属性绑定的形式,把数据传递给子组件

b.子组件中,通过props接受子组件传递过来的数据

<template>
  <div>父组件</div>
  <DemoSon :msg="msg"></DemoSon>
</template>
<script>
import DemoSon from './son.vue'
export default {
    name:'demo',
    components:{DemoSon},
    data(){
        return{
            msg:'111'
        }
    }
}
</script>

<template>
  <div>子组件</div>
  <p>{{ msg }}</p>
</template>
<script>
export default {
    name:'demo-son',
    props:{
        msg:{
            type:[Number,String],
            required:true,
            default:10
        }
    }
}
</script>
2.子传父

a.在v-bind指令前添加v-model指令

b.在子组件中声明emits自定义事件,格式为update:xxx

c.调用$emit()触发自定义事件,更新父组件中的数据

<template>
  <div class="card">
    {{ count }}
    <Son v-model:number="count"></Son>
  </div>
</template>
<script >
import Son from './son.vue'
export default{
  name:'index',
  components: {
    Son
  },
  data(){
    return{
      count:0
    }
  }
}
</script>

<template>
  {{ number }}
  <button type="button" @click="clickFn">按钮</button>
</template>
<script>
export default{
  name:'son',
  props:['number'],
  emits:['update:number'],
  methods:{
    clickFn(){
      this.$emit('update:number',this.number+1)
    }
  }
}
</script>


http://www.kler.cn/a/309743.html

相关文章:

  • 数据结构——二叉树(续集)
  • Swift 开发教程系列 - 第12章:协议与协议扩展
  • C++设计模式精选面试题及参考答案
  • 边缘计算的学习
  • 【JS】如何设置一个只读属性
  • 【CUDA】线程配置
  • 家电制造的隐形守护者:矫平机确保材料完美无瑕
  • Linux 调用write()函数后,内核一般多久将数据写入磁盘
  • Java轻量级测试框架的实现与使用 总篇
  • 【资料分析】刷题日记1
  • 保护您的企业免受网络犯罪分子侵害的四个技巧
  • 【运维监控】Prometheus+grafana监控flink运行情况
  • SpringBoot2:web开发常用功能实现及原理解析-@ControllerAdvice实现全局异常统一处理
  • [苍穹外卖]-10WebSocket入门与实战
  • SpringBoot整合WebSocket实现消息推送或聊天功能示例
  • 从头开始学MyBatis—02基于xml和注解分别实现的增删改查
  • (java+Seleniums3)自动化测试实战2
  • ssh远程连接try1账号切换tips
  • 宝兰德MCP系列介绍 ①:中间件管理能力全线升级,驱动企业数字化管理效能提升
  • node.js 完全卸载和下载配置
  • 五种数据库特性对比(Redis/Mysql/SQLite/ES/MongoDB)
  • 780nm 扫地机器人模组:科技引领智能清洁新潮流
  • windows使用tcpdump.exe工具进行抓包教程
  • 企业如何构建有效的数据泄露防护安全体系
  • [yotroy.cool] MGT 388 - Finance for Engineers - notes 笔记
  • kubelet组件的启动流程源码分析