Javascript 如何将自动调整大小的textarea作为道具传递?在它上面工作';它是自己的,但不是作为道具

Javascript 如何将自动调整大小的textarea作为道具传递?在它上面工作';它是自己的,但不是作为道具,javascript,vue.js,input,vuejs2,textarea,Javascript,Vue.js,Input,Vuejs2,Textarea,我正在为textareas开发一个新组件,希望让它们能够完成三件事自动对焦,去盎司(仍在进行中)和基于值的自动增长/调整大小 我已经得到了一个基本组件,可以使用它,还有一些我不太熟悉的计算属性。但从我的理解来看,我不需要他们来让这些新道具工作 我的自动对焦作为一个道具工作得很好,但是自动增长/调整大小给我带来了一些麻烦。在一个单独的实例中,我可以让它工作,但是作为这个basecomponent的道具传递,我无法让它工作 当我尝试添加:value=“value”使v-model工作时,我得到一个错

我正在为textareas开发一个新组件,希望让它们能够完成三件事<代码>自动对焦,
去盎司
(仍在进行中)和基于值的
自动增长/调整大小

我已经得到了一个基本组件,可以使用它,还有一些我不太熟悉的计算属性。但从我的理解来看,我不需要他们来让这些新道具工作

我的自动对焦作为一个道具工作得很好,但是自动增长/调整大小给我带来了一些麻烦。在一个单独的实例中,我可以让它工作,但是作为这个basecomponent的道具传递,我无法让它工作

当我尝试添加
:value=“value”
使v-model工作时,我得到一个错误:

:value=“value”与同一元素上的v-model冲突,因为后者已在内部扩展为值绑定

我想这是因为它与上面的
v-model=“model”
冲突,但我不确定从那里该如何处理它

我已经附上了在底部工作的版本

我的问题是,我在CcInput-App.vue关系中做错了什么,使它不能像下面的隔离版本那样工作

如果您需要更多信息,请随时询问

CcInput


导出默认值{
名称:“CcInput”,
道具:{
/**v型*/
值:{type:[字符串,数字],默认值:''},
valueType:{type:[字符串,未定义],默认值:未定义},
自动对焦:{type:Boolean,默认值:false},
自动增长:{type:Boolean,默认值:false},
},
安装的(){
如果(此为自动对焦){
if(this.propsToPass.type!=='textarea'){
这是focusInput()
}否则{
this.focusTextArea()
}
}
},
数据(){
返回{
innerValue:this.value,
}
},
方法:{
聚焦输入(){
这是。$refs.input.focus()
},
focusTextArea(){
这是。$refs.textArea.focus()
},
},
计算:{
listenersWithoutInput(){
返回{…this.$listeners,输入:undefined}
},
型号:{
得到(){
返回此.value
},
设置(val){
const{propsToPass}=此
如果(propsToPass.type=='number'){
const valAsNumberIfNotNaN=!isNaN(Number(val))?Number(val):val
此.$emit('input',valAsNumberIfNotNaN)
返回
}
此.$emit('input',val)
},
},
propsToPass(){
常量{$attrs,valueType}=此
常量类型=$attrs.type?$attrs.type:valueType==='number'?'number':未定义
返回{…$attrs,type}
},
},
}
.cc输入
最小宽度:0
最大宽度:100%
显示器:flex
柔性包装:nowrap
对齐项目:居中
职位:相对
文本区,输入
填充:10px
最小宽度:0
宽度:100%
最小高度:24px
线高:24px
大纲:无
盒影:无
-webkit外观:无
边界:无
z指数:2
职位:相对
.cc输入
最小宽度:0
最大宽度:100%
显示器:flex
柔性包装:nowrap
对齐项目:居中
职位:相对
文本区,输入
填充:10px
最小宽度:0
宽度:100%
最小高度:24px
线高:24px
大纲:无
盒影:无
-webkit外观:无
边界:无
z指数:2
职位:相对
背景:无
文本区
框大小:边框框
最小高度:100px!重要的
&::之后,&::之前
边界半径:4px
位置:绝对位置
排名:0
底部:0
左:0
右:0
内容:“”
边框样式:实心
过渡:边框颜色300毫秒
&::之后
边框宽度:1px
边框颜色:rgba(0,0,0,0.24)
&::之前
边框宽度:2倍
边框颜色:透明
&:焦点在::之后
边框颜色:透明
&:焦点在::之前
边框颜色:紫色
App.vue


自动对焦
去盎司
自传
从“../components/CcInput.vue”导入CcInput
导出默认值{
名称:“应用程序”,
组成部分:{
CcInput,
},
}
*
宽度:50vw
左:50%
.文本区
文本对齐:居中
自动增长.vue


导出默认值{
姓名:'自动增长',
},
方法:{
自动增长(e){
e、 target.style.height='auto'
e、 target.style.height=`${e.target.scrollHeight}px`
},
},
}
.文本区
框大小:边框框
宽度:100%
填充:20px
边界半径:8px

该bug位于
propsToPass
computed属性中,其中:

//Ccinput.vue
导出默认值{
计算:{
propsToPass(){
常量{$attrs,valueType}=此
常量类型=$attrs.type?$attrs.type:valueType==='number'?'number':未定义
返回{…$attrs,type}
},
}
}
给定
值类型
“textarea”
propsToPass.type
未定义
,不满足自动增长行为:


解决此问题的一种方法是更新条件以检查
valueType
,而不是
propsToPass.type


并更新为使用
valueType

//如果(this.propsToPass.type!=='textarea'){
if(this.valueType!=='textarea'){
作为旁白,您有:

//this.$refs.textArea.focus()❌
^
这是。$refs.textarea.focus()✅
<template>
  <div class="cc-input">
    <input
      v-if="propsToPass.type !== 'textarea'"
      v-bind="propsToPass"
      v-model="model"
      ref="input"
    />
    <textarea
      v-if="propsToPass.type === 'textarea'"
      v-bind="propsToPass"
      v-model="model"
      ref="textarea"
    />
  </div>
</template>


<script>

export default {
  name: 'CcInput',
  props: {
    /** v-model */
    value: { type: [String, Number], default: '' },
    valueType: { type: [String, undefined], default: undefined },
    autofocus: { type: Boolean, default: false },
    autogrow: { type: Boolean, default: false },
  },
  mounted() {
    if (this.autofocus) {
      if (this.propsToPass.type !== 'textarea') {
        this.focusInput()
      } else {
        this.focusTextArea()
      }
    }
  },
  data() {
    return {
      innerValue: this.value,
    }
  },
  methods: {
    focusInput() {
      this.$refs.input.focus()
    },
    focusTextArea() {
      this.$refs.textArea.focus()
    },
  },
  computed: {
    listenersWithoutInput() {
      return { ...this.$listeners, input: undefined }
    },
    model: {
      get() {
        return this.value
      },
      set(val) {
        const { propsToPass } = this
        if (propsToPass.type === 'number') {
          const valAsNumberIfNotNaN = !isNaN(Number(val)) ? Number(val) : val
          this.$emit('input', valAsNumberIfNotNaN)
          return
        }
        this.$emit('input', val)
      },
    },
    propsToPass() {
      const { $attrs, valueType } = this
      const type = $attrs.type ? $attrs.type : valueType === 'number' ? 'number' : undefined
      return { ...$attrs, type }
    },
  },
}
</script>

<style lang="sass">
.cc-input
  min-width: 0
  max-width: 100%
  display: flex
  flex-wrap: nowrap
  align-items: center
  position: relative
  textarea, input
    padding: 10px
    min-width: 0
    width: 100%
    min-height: 24px
    line-height: 24px
    outline: none
    box-shadow: none
    -webkit-appearance: none
    border: none
    z-index: 2
    position: relative
.cc-input
  min-width: 0
  max-width: 100%
  display: flex
  flex-wrap: nowrap
  align-items: center
  position: relative
  textarea, input
    padding: 10px
    min-width: 0
    width: 100%
    min-height: 24px
    line-height: 24px
    outline: none
    box-shadow: none
    -webkit-appearance: none
    border: none
    z-index: 2
    position: relative
    background: none
  textarea
    box-sizing: border-box
    min-height: 100px !important

  &::after, &::before
    border-radius: 4px
    position: absolute
    top: 0
    bottom: 0
    left: 0
    right: 0
    content: ''
    border-style: solid
    transition: border-color 300ms ease
  &::after
    border-width: 1px
    border-color: rgba(0, 0, 0, 0.24)
  &::before
    border-width: 2px
    border-color: transparent
  &:focus-within::after
    border-color: transparent
  &:focus-within::before
    border-color: purple
</style>

<template>
  <div class="home">
    <div class="textarea">
        autofocus
        <CcInput valueType="textarea" :autofocus="true" />
      </div>
      <div class="textarea">
        debounce
        <CcInput valueType="textarea" :debounce="300" />
      </div>
      <div class="textarea">
        autogrow
        <CcInput valueType="textarea" :autogrow="true" />
      </div>
    </div>
  </div>
</template>

<script>
import CcInput from '../components/CcInput.vue'
export default {
  name: 'App',
  components: {
    CcInput,
  },
}
</script>

<style lang="sass" scoped>
*
  width: 50vw
  left: 50%
.textarea
  text-align: center
</style>
<template>
  <div>
    <textarea class="textarea" name="body" id="body" @input="autogrow($event)"></textarea>
    <textarea class="textarea" name="anotherbody" id="anotherbody"></textarea>
  </div>
</template>
<script>
export default {
  name: 'Autogrow',
  },
  methods: {
    autogrow(e) {
      e.target.style.height = 'auto'
      e.target.style.height = `${e.target.scrollHeight}px`
    },
  },
}
</script>
<style lang="sass" scoped>
.textarea
  box-sizing: border-box
  width: 100%
  padding: 20px
  border-radius: 8px
</style>