【问题标题】:TextArea Avoid mutating a prop directly since the value will be overwrittenTextArea 避免直接改变道具,因为该值将被覆盖
【发布时间】:2021-09-05 14:30:07
【问题描述】:

我知道类似的问题已经在 stackoverflow 上得到处理。但我无法从提议的解决方案中找到解决方案。我很惭愧。

本质是这样的:我有一个组件和另一个在里面。 子组件-VClipboardTextField是一个现成的配置text-area。我无法将输入从那里取出,而且我在尝试输入时也没有收到错误消息。

避免直接改变prop,因为值会被覆盖 每当父组件重新渲染时。相反,使用数据或 基于道具值的计算属性。道具被变异: “消息”

代码 tabs-item.vue

<template>
  <v-container fluid>
    <v-row align="center">
      <v-col cols="9">
        <v-card flat>
          <v-card-text>
            <h1>Request</h1>
            <v-container>
              <v-textarea v-model="message"
                          placeholder="Placeholder"
                          label="Request"
                          auto-grow
                          clear-icon="mdi-close-circle-outline"
                          clearable
                          rows="10"
                          row-height="5"


                          @click:clear="clearMessage"
              ></v-textarea>
              <v-textarea v-model="response"
                          placeholder="Placeholder"
                          label="Request2"
                          auto-grow
                          counter
                          rows="10"
                          row-height="5"
                          color="success"
              ></v-textarea>

              <VClipboardTextField ></VClipboardTextField>
              <VClipboardTextField isReadOnly></VClipboardTextField>
            </v-container>

            <v-row>

              <v-btn
                dark
                color="primary"
                elevation="12"
                justify="end"
                float-right
                @click="sendRequest"
              >
                Send Request
              </v-btn>
            </v-row>
          </v-card-text>
        </v-card>
      </v-col>

      <v-col cols="3">
        <schema-selector @changeSchema="onChangeSchema"></schema-selector>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: 'tabs-item',
  props: ['response'],
  data() {
    return {
      schema: String,
      message: '',
    }
  },
  methods: {
    sendRequest() {
      const message = {
        message: this.message,
        method: this.schema.state
      }
      this.$emit('sendRequest', message)
    },
    clearMessage() {
      this.message = ''
    },
    onChangeSchema(selectS) {
      console.log("get schema: ", selectS.state)
      this.schema = selectS

    }
  },

}
</script>

和子 VClipboardTextField.vue

<template>
  <v-container>
    <v-tooltip bottom
               v-model="show">
      <template v-slot:activator="{ on, attrs }">
        <v-textarea
          v-model="message"
          :append-outer-icon="'mdi-content-copy'"
          :readonly="isReadOnly"
          auto-grow
          filled
          counter
          clear-icon="mdi-close-circle-outline"
          clearable
          label="Response message"
          type="text"
          @click:append-outer="copyToBuffer"
          @click:clear="clearMessage"
        ></v-textarea>

      </template>
      <span>Tooltip</span>
    </v-tooltip>
  </v-container>
</template>

<script>
export default {
  name: 'VClipboardTextField',
  props: {
    isReadOnly: Boolean,
    message : { type :String, default: "msg"}
  },
  data() {
    return {
      show: false,
    //  messageLocal: 'Response!',
      iconIndex: 0,
    }
  },
  methods: {
    copyToBuffer() {
      console.log("this: ", this)
      navigator.clipboard.writeText(this.message);
      this.toolTipChange()
      setTimeout(() => this.toolTipChange(), 1000)
    },
    clearMessage() {
      this.message = ''
    },
    toolTipChange() {
      if (this.show)
        this.show = false
    }
  }
}
</script>

我很高兴看到一个代码示例,该示例将解释如何在没有拐杖的情况下正确解决此问题! 谢谢。

【问题讨论】:

    标签: javascript node.js vue.js nuxt.js vuetify.js


    【解决方案1】:

    你不能修改组件中的props,如果需要message的初始值作为占位符(意味着输入可能一开始不为空),你可以将数据存储在messageprop到另一个数据变量并将其用作v-modeltextarea。 如果 message 没有初始值,只需为 textarea 使用另一个数据变量,并在 watcher 中为 message 发出更新。

    代码 tabs-item.vue

    <VClipboardTextField :message.sync="message"></VClipboardTextField>
    

    和子 VClipboardTextField.vue

    <template>
      <v-container>
        <v-tooltip bottom
                   v-model="show">
          <template v-slot:activator="{ on, attrs }">
            <v-textarea
              v-model="message_slug"
              :append-outer-icon="'mdi-content-copy'"
              :readonly="isReadOnly"
              auto-grow
              filled
              counter
              clear-icon="mdi-close-circle-outline"
              clearable
              label="Response message"
              type="text"
              @click:append-outer="copyToBuffer"
              @click:clear="clearMessage"
            ></v-textarea>
    
          </template>
          <span>Tooltip</span>
        </v-tooltip>
      </v-container>
    </template>
    
    <script>
    export default {
      name: 'VClipboardTextField',
      props: {
        isReadOnly: Boolean,
        message : { type :String, default: "msg"}
      },
      data() {
        return {
          show: false,
        //  messageLocal: 'Response!',
          iconIndex: 0,
          message_slug: '',
        }
      },
      watch: {
        message_slug(x) {
          this.$emit('update:message', x)
        }
      },
    }
    </script>
    

    它将值绑定到message_slug,并在其值更改时更新父组件上的message

    【讨论】:

      【解决方案2】:

      不是每次都观察变化,你只能在有变化时发出。

      在你的 tabs-item.vue

      <VClipboardTextField v-model="message"></VClipboardTextField>
      

      在您的 VClipboardTextField.vue 组件中,您可以接收 v-model 输入道具作为“VALUE”道具并将其分配给本地数据属性。这样你就可以操纵本地属性,并且只有在它被改变时才发出!

      <template>
        <v-container>
          <v-tooltip bottom v-model="show">
            <template v-slot:activator="{ on, attrs }">
              <v-textarea
                v-model="message"
                :append-outer-icon="'mdi-content-copy'"
                :readonly="isReadOnly"
                v-on="on"
                v-bind="attrs"
                auto-grow
                filled
                counter
                clear-icon="mdi-close-circle-outline"
                clearable
                label="Response message"
                type="text"
                @click:append-outer="copyToBuffer"
                @click:clear="clearMessage"
                @change="$emit('input', v)"
              ></v-textarea>
            </template>
            <span>Tooltip</span>
          </v-tooltip>
        </v-container>
      </template>
      
      <script>
      export default {
        name: "VClipboardTextField",
        props: {
          isReadOnly: { type: Boolean },
          value: {
            type: String,
          },
        },
        data() {
          return {
            show: false,
            message: this.value,
          };
        },
      };
      </script>
      

      【讨论】:

        猜你喜欢
        • 2017-03-27
        • 2017-11-28
        • 2021-03-02
        • 2022-11-02
        • 2020-09-12
        • 2017-05-04
        • 2021-08-12
        • 2020-05-21
        • 2019-08-19
        相关资源
        最近更新 更多