首先说下 父子组件传递值的问题:
父页面传给子组件使用 props
子组件传回给父页面使用 emit
在以前的时候,子组件的值传回来后,父页面需要写一个事件用来赋值,做不到自动更新。(具体怎么使用组件这里就不多说了)
本文就是为了解决这个麻烦的问题,效果就是,子组件封装好后,父组件只需要使用 不需要做其他处理。
根据上面的问题,下面写一个组件用来计数textarea输入的值的长度,有限制字数的功能
(下面是基于vue element框架,ps:element里面有这个功能,但是有些许不一样)
element使用如下:
<el-input
type="textarea"
placeholder="请输入内容"
v-model="textarea"
maxlength="30"
show-word-limit
>
</el-input>
具体可查看element的文档https://element.eleme.cn/#/zh-CN/component/input
下面介绍下本人自己写的组件:(代码为了可以直接拿去使用,有些冗余,可以直接滑到最底下看注意点)
//子组件完整代码
<template>
<div class="mytextarea_wrap">
<div @mouseenter="ishover = true" @mouseleave="ishover = false" :class="{focusPar:isfocus,hoverPar:ishover}">
<el-input type="textarea"
v-model="value"
:autosize="autosize"
@input="changeFun"
@focus="isfocus = true"
@blur="isfocus = false"
:placeholder="placeholder">
</el-input>
<span class="mytextarea_count" :class="{focus:isfocus,hover:ishover}">{{value.length}}/{{limit}}</span>
</div>
<span class="mytextarea_tips" v-show="value.length>limit">输入字符不能超过{{limit}}个字符</span>
</div>
</template>
<script>
export default {
data(){
return{
value : this.val || '',
isfocus : false,
ishover : false,
}
},
watch: {
val(nv){
this.value = nv;
}
},
props: {
autosize : {
type : Object,//Array 和 Object 默认值必须使用函数return回来
default : function () {
return { minRows: 4, maxRows: 6 }
}
},
placeholder : String,
limit : {
type : [String, Number],
default : 500,
},
val : String,
},
methods:{
changeFun(){
this.$emit('update:val',this.value);
}
}
}
</script>
<style lang="scss">
@import '../sass/color';
.mytextarea_wrap{
.el-textarea__inner{
border-radius: 4px 4px 0 0;
border-bottom: none;
resize: none;
}
.mytextarea_count{
display: block;
width: 100%;
box-sizing: border-box;
font-size: 12px;
padding: 0 15px;
height: 24px;
line-height: 24px;
text-align: right;
border-radius: 0 0 4px 4px;
border: 1px solid #dcdfe6;
border-top: 0;
color: #999;
transition: border-color .2s cubic-bezier(.645,.045,.355,1);
}
.mytextarea_count.focus{
border-color: $pageColor_blue !important;
}
.mytextarea_count.hover{
border-color: #C0C4CC;
}
.hoverPar{
textarea{
border-color: #C0C4CC;
}
}
.focusPar{
textarea{
border-color: $pageColor_blue !important;
}
}
.mytextarea_tips{
display: block;
height: 24px;
line-height: 24px;
color: $pageColor_red;
font-size: 12px;
}
}
</style>
父页面使用如下:
<textarea-limitnew
:val.sync="applyServiceData.reason"
placeholder="请描述申请售后服务的具体原因"
limit="50"
></textarea-limitnew>
需要注意的几个位置:
1.props 里面给默认值的时候,如果type是Array 或 Object,需要使用函数return回来,如上代码props里面autosize
2.props 如果type是多个类型,可用数组表示,如上代码props里面limit
3.props传进来的值 不能被更改,所以传进来的val, 我们使用value保存一下,然后操作value。另外有个问题,组件只会在创建的时候 赋值一次,所以我在页面加了个watch监听val,避免出现如下问题:比如我们有个弹框使用的是v-show,没用v-if。弹框里面有这个组件,当我们第一次打开弹框的时候val和value都为空,我们编辑后val和value都有值了,然后在父页面关掉弹框,并且重置值。接下来再打开弹框的时候,会发现val在父页面被清空了,但是value在子组件里面还是上次的值,所以需要加个watch再赋值一遍。(用v-if的话忽略这点)
4.如果想在父组件调用子组件里面的方法(比如函数名为childFun),可以给子组件加上ref="test",在父组件中使用this.$refs.test.childFun()
就可以调用到了
5.接下来这点就是本文的主题了。使用组件的时候带上.sync
修饰符,然后在子组件里面emit的时候写法如上代码this.$emit('update:val',this.value);
update:val
里面的val是传进来的值的字段名字。这样子在父页面就不需要赋值一次了。
最后效果如下:



网友评论