美文网首页
vue组件数据自动更新sync

vue组件数据自动更新sync

作者: 索哥来了 | 来源:发表于2019-04-29 17:13 被阅读0次

    首先说下 父子组件传递值的问题:
    父页面传给子组件使用 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是传进来的值的字段名字。这样子在父页面就不需要赋值一次了。

    最后效果如下:


    image.png image.png image.png

    相关文章

      网友评论

          本文标题:vue组件数据自动更新sync

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