乐趣区

关于vue.js:组件传值数据双向绑定

一、组件传值

组件间的传值形式

父子传值:props、emit、$parent、$chidren、ref
兄弟之间传值:事件总线(on、emit)、Vuex

传值实例

(1)父组件传到子组件 (props)
一个组件默认能够领有任意数量的 prop,任何值都能够传递给任何 prop。

// 父组件
<template>
    <div>
        <ceshi @test="test"></ceshi>
    </div>
</template>
<script>
export default {data() {test: '测试'}
}
</script>

// 子组件接管 ceshi
<template>
    <div>
        {{test}}
    </div>
</template>
<script>
export default {
    props: {test: String}
    data() {}
}
</script>

(2)子组件传到父组件 (emit)
子组件通过 emit 触发事件给父组件,父组件通过 on 去监听数据的变动。

// 父组件
<template>
    <div>
        <ceshi :test="test" @change="change"></ceshi>
    </div>
</template>
<script>
export default {data() {test: '测试'},
    methods: {change(val){console.log(val)
       }
    }
}
</script>

// 子组件接管 ceshi
<template>
    <div>
        {{test}}
        <button @click="getTitle"></button>
    </div>
</template>
<script>
export default {
    `props: {test: String}`
    data() {title: '子组件'},
    methods: {getTitle(){this.$emit('change', this.title) // 将值绑定到 change 上传递过来
       }
    }
}
</script>

二、prop

prop 类型

以字符串模式列出:

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

通常咱们都须要每个 prop 都有指定的值类型,因而通过对象的模式列出、别离表明 prop 的名称和类型以及默认值

props: {
   test: String,
   likes: {
       type: Number,
       default: () => []
   },
   isPublished: {
       type: Boolean,
       default: false
   }
}

传递动态或动静 Prop

// 动态传值
<blog-post title="My journey with Vue"></blog-post>

// 动静赋予一个变量的值
<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。如果你这样做了,Vue 会在浏览器的控制台中收回正告。

须要扭转 prop 时,能够通过

(1)子组件内须要将 prop 作为本地数据进行应用,能够在 data 中将这个 prop 作为初始值

props: ['initialCounter'],
data: function () {
  return {counter: this.initialCounter}
}

(2)这个 prop 以一种原始的值传入且须要进行转换。在这种状况下,最好应用这个 prop 的值来定义一个计算属性:

props: ['size'],
computed: {normalizedSize: function () {return this.size.trim().toLowerCase()}
}

留神在 JavaScript 中对象和数组是通过援用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中扭转变更这个对象或数组自身将会影响到父组件的状态。

三、自定义事件(v-model)

双向绑定 v -model

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,然而像单选框、复选框等类型的输出控件可能会将 value attribute 用于不同的目标。model 选项能够用来防止这样的抵触:

// 子组件
<template>
    <div>
        <el-input v-model="price" @input="updateVal"></el-input>
    </div>
</template>
<script>
export default {
   // model 用于扭转 v -model 绑定的属性和抛出事件(实时监听)model: {
        prop: 'price',
        event: 'change'
   },
    props: {price: Number},
    methods: {updateVal(val){this.$emit('change', val) // 监听 price 值变动,传递给父组件
       }
    }
}
</script>

在父组件应用 v -model,通过该语句实现 price 变量与输出值双向绑定

<ceshi @change="change" v-model="price"></ceshi>


// 等同于
<ceshi @change="change" :value="price" @input="price=$event.target.value"></ceshi>

执行流程:
1、子组件通过通过 prop 接管父组件的数据 price
2、当 input 进行输出时,会触发 input 事件
3、通过 $emit 提交事件,将值传递给父组件
4、父组件的 input 事件被触发,将会更新变量 price 的值
5、父组件在通过 props 传值给子组件

v-bind 实现单向绑定
v-model 实现双向绑定

.sync 修饰符

真正的双向绑定会带来保护上的问题,因为子组件能够变更父组件,且在父组件和子组件两侧都没有显著的变更起源。因而举荐update:myPropName 的模式触发事件

vue 事件名能够 updata:prop 去定义,用于解决 prop 传递的新值
组件外部将通过 $emit(‘update:dtitle’, val)触发事件,批改 title 的值

// 子组件
<el-input v-model="title" @input="updateVal"></el-input>

props: ['title'],
updateVal(val) {this.$emit('update:dtitle', val)
}
// 父组件
<ceshi @update:dtitle="title = $event" :title.sync="title"></ceshi>

注意事项:
1、.sync 修饰符的 v-bind 不能和表达式一起应用
2、组件外部须要 $emit 触发的事件名,格局为 update:prop

同时在应用 sync 的时候,简化了绑定 prop 和绑定 update:prop 事件

四、动静组件 & 异步组件

五、代码实例

退出移动版