Content list encapsulated by Vue component (processing multi-line input box textarea)

Content list encapsulated by Vue component

1. Content list

Component description:
realize the layout and typesetting of Content list.

Show results:

Insert picture description here

Realized functions:

  1. Realize the up and down layout of text and input boxes (single line/multiple lines) in a List;
  2. Above is the text label, which is displayed in plain text. You can use the require field to determine whether it is required. Required fields will have a red * in front.
  3. Below is the input value input/textarea tag.

Two, use cases

<template>
     <div>
     <el-context
          :list="contentList"        
          :result="contentItem"        
        />
      </div>
</template>
<script>
export default {
    
    
  data(){
    
    
     return {
    
    
        contentList:[
            {
    
    title:"工作内容",require:true,field:"content",placeholder:'请输入工作内容。如休假请填休假(240字以内)',
              renderType:'textarea',
              maxLength:"240"
            },
            {
    
    title:"时长",require:true,field:"time",placeholder:'请输入小时数,保留一位小数。如休假请填0',renderType:'number'},
            {
    
    title:"备注",require:false,field:"remark",placeholder:'请输入备注(240字以内)',
              renderType:'textarea',maxLength:"240",dealWithKeyboard:true},
          ],
        contentItem:{
    
    
          content:'',
          time:'',
          remark:'',
        },
     
    }
  }
}
</script>	

3. API usage guide

Attributes Description Types of Defaults
list The static content collection displayed on the page Array []
renderType Component type String
maxLength Maximum length limit String
label Display text String
field Enter value field String
placeholder prompt String
require Is it a required field Boolean
disabled The value is true or disabled, it is the reversed value, otherwise it is the input value Boolean false
dealWithKeyboard Whether to deal with Android keyboard occlusion problem Boolean false
result Corresponding field value collection Object {}

Fourth, the source code

Context.vue
file path: share/context/Context.vue

<template>
  <div>
    <div v-for="item in list">
      <div class="cm-p-02 cm-bottom">
        <div class="cm-fs-030">
          <span class="cm-c-red" v-if="item.require">*</span>
          <span :class="[focusText==item.field?'edit-focus-text':'',!item.require?'cm-ml-02':'']">{
    
    {
    
    item.title}}</span>
        </div>
        <el-input
          v-if="item.renderType==='number'"
          @focus="changeStyle(item)"
          type="text"
          @input.native="changeNumber"
          :placeholder="item.placeholder"
          class="edit-input cm-w-full cm-fs-028 cm-c-333"
          v-model="result[item.field]"></el-input>
        <el-input
          :type="item.renderType"
          v-else
          @focus="changeStyle(item)"
          :autosize="{ minRows: 2, maxRows: 4}"
          :maxlength="item.maxLength"
          class="edit-input cm-w-full cm-fs-028 cm-c-333"
          :placeholder="item.placeholder"
          rows="2"
          v-model="result[item.field]">
        </el-input>
      </div>
    </div>
  </div>
</template>
<script>
  import {
    
    autoTextarea,isAndroid} from '../../utils/common';
  export default {
    
    
    name: "ElContent",
    data(){
    
    
      return{
    
    
        focusText:""
      }
    },
    //获取子组件传过来的激活tab
    props:{
    
    
      list:{
    
    
        type: Array,
        default: function () {
    
    
          return [];
        }
      },
      result:{
    
    
        type:Object,
        default:{
    
    }
      },
    },
    mounted(){
    
    
        //为了适应苹果浏览器初始时展现多行状态。
      setTimeout(() => {
    
    
        autoTextarea();
      }, 100);
    },
    methods:{
    
    
      changeNumber({
    
    target}){
    
    
        //此为数字输入框,控制非数字输入
        target.value=(target.value.match(/^\d*(\.?\d{0,1})/g)[0]) || null
      },
      changeStyle(item){
    
    
        //聚焦时改变label样式
        this.focusText = item.field;
        //避免安卓手机输入法弹出框挡住输入框
        if(item.dealWithKeyboard && isAndroid()){
    
    
          document.body.style.height = document.body.clientHeight + 100 +'px';
        }
      }
    }
  }
</script>

<style scoped>
  .edit-focus-text{
    
    
    color: #3296FA;
    font-size: 0.22rem;
  }
</style>
export function isAndroid(){
    
    
  var u = navigator.userAgent;
  var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
  if (isAndroid) {
    
    
    return true
  }else {
    
    
    return false
  }
}
export function autoTextarea(){
    
    
  var textarea = document.getElementsByTagName("textarea");
  for(var i=0;i<textarea.length;i++){
    
    
    textarea[i].style.height = 'auto';
    textarea[i].scrollTop = 0; //防抖动
    textarea[i].style.height = textarea[i].scrollHeight + 'px';
    textarea[i].addEventListener('input',function (e) {
    
    
      console.log(e.target.scrollHeight);
      e.target.style.height = 'auto';
      e.target.scrollTop = 0;
      if(e.target.scrollHeight>=100){
    
    
        //控制最高4行
        e.target.style.height = 100 + 'px';
      }else {
    
    
        e.target.style.height = e.target.scrollHeight + 'px';
      }
      //}
    })
  }
}

index.js
file path: share/context/index.js

import Content from './Content.vue';

/* istanbul ignore next */
Content.install = function(Vue) {
    
    
  Vue.component(Content.name, Content);
};

export default Content;

Note: Some public styles are used in it, and there are many public styles, so they will not be posted. There is a need to leave a message.

Guess you like

Origin blog.csdn.net/weixin_44135121/article/details/109114465