您的位置:  首页 > 技术 > 前端 > 正文

props/$emit、v-model、.sync的适用场景 -- vue组件通信系列

2021-10-21 19:00 OSCHINA PHP开发工程师 次阅读 条评论

vue组件的数据通信方式很多,本篇着重讲props/$emit,神助是v-model/.sync语法糖。

   

TL;DR

  • props/$emit是父子组件最常用的通信方式,而v-model、.sync只是其语法糖
  • 子组件只是单一的修改某个父组件值的话,表单类组件使用v-model语法糖
  • 子组件只是单一的修改某个父组件值的话,非表单类组件使用sync语法糖
  • 复杂逻辑还是老老实实props/$emit

其实语法糖只是在父组件用的时候更加方便,而子组件该咋样还是咋样。

   

props/$emit

子组件想要显示父组件的数据,就props。 子组件想要改变父组件的数据,就$emit

props_emit

留意的点:

  • 子组件props里定义的属性名和父组件里的一一对应,注意父组件使用属性的时候用羊肉串格式
  • 父组件的监听事件名和子组件的触发事件名必须一模一样
  • 子组件触发事件的时候,传过来的参数,父组件可以用$event接收
   

v-model语法糖

v-model是属性value和事件input的语法糖。

v-model1

没有语法糖的时候,这样写

用v-model的话,父组件就可以少了监听事件,用起来更加方便

v-model的语法糖有其局限性:

  • 适用于:触发事件返回的值 正是 属性要改的值,一般是单一属性。比如触发事件返回的值正好就是提title的新值
  • 更多逻辑的话,就不适用了
  • 更适用于:表单类的组件,因为属性和事件默认是valueinput

当然特定情况下,可以修改v-model的默认属性,但可读性就不是很好。

export default {

  name:'ListItem',

  model:{

    prop:'title',

    input:'changeTitle'

  }

}

复制代码
       

.sync语法糖

.sync这个语法糖,同样适用于触发事件返回的值 正是 属性要改的值,可读性要强一些,可以用于非表单类的组件。 .sync语法糖默认是 属性xxx和事件update:xxx

v-model1

没有语法糖的时候,这样写

用.sync的话,父组件仍然可以少监听事件,用起来更加方便

sync的语法糖有其局限性:

  • 适用于:触发事件返回的值 正是 属性要改的值,一般是单一属性。比如触发事件返回的值正好就是提title的新值
  • 更多逻辑的话,就不适用了
  • 更适用于:非表单类的组件
   

总结

  • props/$emit是父子组件最常用的通信方式,而v-model、.sync只是其语法糖
  • 子组件只是单一的修改某个父组件值的话,表单类组件使用v-model语法糖
  • 子组件只是单一的修改某个父组件值的话,非表单类组件使用sync语法糖
  • 复杂逻辑还是老老实实props/$emit

其实语法糖只是在父组件用的时候更加方便,而子组件该咋样还是咋样。

   

代码

   

props/$emit的代码

List.vue

<template lang="pug">

//- 父组件

div

  //- item就是传递给ListItem的数据,属性是info

  //- clickLike,就是监听ListItem的clickLike事件

  list-item(v-for="(item,index) in list" :key="index"

  :info="item"

  v-on:clickLike="change(item,$event)")

</template>

<script>

import ListItem from "@/components/ListItem";

export default {

  name: "List",

  components: { ListItem },

  data() {

    return {

      list: [

        { title: "vue3来了", collects: 20 },

        { title: "怜怜来了", collects: 2000 }

      ]

    };

  },

  methods: {

    // 当clickLike事件发生的时候,执行此方法

    // 这里的event是ListItem传过来的值

    change(item, event) {

      item.collects = event;

    }

  }

};

</script>



复制代码
   

DetailItem.vue

<template lang="pug">

//- 子组件

div

  h2 {{info.title}}

  span 喜欢数 {{info.collects}}

  div

    button(@click="addCollect") 喜欢

  hr

</template>

<script>

export default {

  name: "ListItem",

  props: {

    // 这里定义父组件传过来的属性

    info: { type: Object, default: () => ({}) }

  },

  methods: {

    addCollect() {

      // 触发此组件的clickLike时间,并且传一个值给父组件

      this.$emit("clickLike", this.info.collects + 1);

    }

  }

};

</script>



复制代码
       

v-model代码

没有简写时候的代码

<template lang="pug">

//- 父组件

div

  list-item(:value="title" v-on:input="change")

</template>

<script>

import ListItem from "@/components/ListItem";

export default {

  name: "List",

  components: { ListItem },

  data() {

    return {

      title: "怜怜来了"

    };

  },

  methods: {

    // 当clickLike事件发生的时候,执行此方法

    // 这里的event是ListItem传过来的值

    change(event) {

      this.title = event;

    }

  }

};

</script>



复制代码
   
<template lang="pug">

//- 子组件

div {{value}}

  button(@click="changeTitle") 修改标题

</template>

<script>

export default {

  name: "ListItem",

  props: {

    value: { type: String, default: "" }

  },

  methods: {

    changeTitle() {

      this.$emit("input", "换标题啦");

    }

  }

};

</script>



复制代码
   

简写时候的父组件代码

<template lang="pug">

//- 父组件

div

  list-item(v-model="title")

</template>

<script>

import ListItem from "@/components/ListItem";

export default {

  name: "List",

  components: { ListItem },

  data() {

    return {

      title: "怜怜来了"

    };

  }

};

</script>



复制代码
       

.sync的代码

没有简写的时候

<template lang="pug">

//- 父组件

div

  list-item(:theme="title" v-on:update:theme="change")

</template>

<script>

import ListItem from "@/components/ListItem";

export default {

  name: "List",

  components: { ListItem },

  data() {

    return {

      title: "怜怜来了"

    };

  },

  methods: {

    // 当clickLike事件发生的时候,执行此方法

    // 这里的event是ListItem传过来的值

    change(event) {

      this.title = event;

    }

  }

};

</script>



复制代码
   
<template lang="pug">

//- 子组件

div {{theme}}

  button(@click="changeTitle") 修改标题

</template>

<script>

export default {

  name: "ListItem",

  props: {

    theme: { type: String, default: "" }

  },

  methods: {

    changeTitle() {

      this.$emit("update:theme", "换标题啦");

    }

  }

};

</script>



复制代码
   

简写的时候,父组件的代码

<template lang="pug">

//- 父组件

div

  //- list-item(:theme="title" v-on:update:theme="change")

  list-item(:theme.sync="title")

</template>

<script>

import ListItem from "@/components/ListItem";

export default {

  name: "List",

  components: { ListItem },

  data() {

    return {

      title: "怜怜来了"

    };

  }

  // methods: {

  //   // 当clickLike事件发生的时候,执行此方法

  //   // 这里的event是ListItem传过来的值

  //   change(event) {

  //     this.title = event;

  //   }

  // }

};

</script>

复制代码
 
     

最后

如果你觉得此文对你有一丁点帮助,点个赞。或者可以加入我的开发交流群:1025263163相互学习,我们会有专业的技术答疑解惑

如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点star: http://github.crmeb.net/u/defu 不胜感激 !

  • 0
    感动
  • 0
    路过
  • 0
    高兴
  • 0
    难过
  • 0
    搞笑
  • 0
    无聊
  • 0
    愤怒
  • 0
    同情
热度排行
友情链接