# Prop

# Prop 的大小写 (camelCase vs kebab-case)

HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名:

Vue.component('blog-post', {
  // 在 JavaScript 中是 camelCase 的
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>

如果你使用字符串模板,那么这个限制就不存在了。

# 传递静态或动态 Prop

像这样,你已经知道了可以像这样给 prop 传入一个静态的值:

<blog-post title="My journey with Vue"></blog-post>

你也知道 prop 可以通过 v-bind 动态赋值,例如:

<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"></blog-post>

<!-- 动态赋予一个复杂表达式的值 -->
<blog-post
  v-bind:title="post.title + ' by ' + post.author.name"
></blog-post>

在上述两个示例中,我们传入的值都是字符串类型的,但实际上任何类型的值都可以传给一个 prop。

# 单向数据流 父子 prop

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

# Image Example

KycForm.vue 父

<kyc-image v-for="img in imgArr"
    :key="img.pos"
    :text="img.text"
    :imgSrc.sync="form.imageList[img.pos]"
    :id="`img_${img.pos}`"
    class="mt-3">
</kyc-image>

KycImage.vue 子

<input accept="image/jpeg, image/png"
    type="file"
    :id="(id)"
    @change="handleLoad"
    :class="[$style.idimg__input]" />
  // props 父組件 傳遞資料給 子組件
  props: {
    imgSrc: {
      type: String,
      default: null
    },
  methods: {
    handleLoad(evt) {
      this.isLoading = true
      const imgFile = evt.target.files[0]
      // console.log(imgFile, 'orig image')
      if (!imgFile) {
        this.applyStyle(null)
        return
      } else {
        this.applyStyle(this.imgSrc) // this.imgSrc 從props來 
        return
      }
    },
    /**
     * 將圖片套用在CSS
     */
    applyStyle(src) {
      const imgStyle = this.$refs[this.id].style // $refs 取得 DOM Element 的資訊
      imgStyle.backgroundImage = ''
      if (src) {
        imgStyle.backgroundImage = `url(${src})`
        this.$emit('update:imgSrc', src) // 子組件 傳遞資料給 父組件 
        imgStyle.backgroundRepeat = 'no-repeat'
        imgStyle.backgroundPosition = 'center'
        imgStyle.backgroundSize = 'contain'
      } else {
        this.$emit('update:imgSrc', '')
      }
      this.isLoading = false
    },