Vueコンポーネントによってカプセル化されたコンテンツリスト(複数行の入力ボックスtextareaの処理)

Vueコンポーネントによってカプセル化されたコンテンツリスト

1.コンテンツリスト

コンポーネントの説明:
コンテンツリストのレイアウトとタイプ設定を実現します。

結果を示す:

ここに写真の説明を挿入

実現した機能:

  1. リスト内のテキストと入力ボックス(単一行/複数行)の上下のレイアウトを実現します。
  2. 上はプレーンテキストで表示されるテキストラベルです。requireフィールドを使用して、必須かどうかを判断できます。必須フィールドの前には赤い*が表示されます。
  3. 以下は、入力値input / textareaタグです。

2、ユースケース

<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使用ガイド

属性 説明 の種類 デフォルト
リスト ページに表示される静的コンテンツコレクション アレイ []
renderType コンポーネントタイプ ストリング
maxLength 最大長制限 ストリング
ラベル テキストを表示する ストリング
フィールド 値フィールドを入力 ストリング
プレースホルダー 促す ストリング
必要とする 必須フィールドですか ブール値
無効 値が真または無効の場合は逆の値、それ以外の場合は入力値です ブール値 false
dealWithKeyboard Androidキーボードの閉塞の問題に対処するかどうか ブール値 false
結果 対応するフィールド値の収集 オブジェクト {}

第四に、ソースコード

Context.vue
ファイルパス: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
ファイルパス:share / context / index.js

import Content from './Content.vue';

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

export default Content;

注:一部のパブリックスタイルが使用されていますが、パブリックスタイルが多いため、投稿されません。メッセージを残す必要があります。

おすすめ

転載: blog.csdn.net/weixin_44135121/article/details/109114465