属性
1.自定义属性props
prop 定义了这个组件有哪些可配置的属性,组件的核心功能也都是它来确定的。写通用组件时,props 最好用对象的写法,这样可以针对每个属性设置类型、默认值或自定义校验属性的值,这点在组件开发中很重要,然而很多人却忽视,直接使用 props 的数组用法,这样的组件往往是不严谨的。
<props name='属性'
:type='type'
:is-visible="false"
:currentIndex="currentIndex"
:on-change="handlePropChange"
:list=[22, 33, 44]
aaa="1111"
class="test1"
:class="['test2']"
:style="{ marginTop: '20px' }" //注意:style 的优先级是要高于 style
style="margin-top: 10px"
</props>
// 子组件
props: {
name: String,
type: {
//从父级传入的 type,它的值必须是指定的 'success', 'warning', 'danger'中的一个,如果传入这三个以外的值,都会抛出一条警告
validator: (value) => {
return ['success', 'warning', 'danger'].includes(value)
}
},
// 多个可能的类型,可能是Number类型也可能是String类型
currentIndex: {
type: [Number, String],
default: 0
},
onChange: {
//对于接收的数据,可以是各种数据类型,同样也可以传递一个函数
type: Function,
default: () => { }
},
isVisible: {
type: Boolean,
default: false
},
list: {
type: Array,
// 对象或数组默认值必须从一个工厂函数获取
default: () => []
}
}
从上面的例中,可以得出props可以显示定义一个或一个以上的数据,对于接收的数据,可以是各种数据类型,同样也可以传递一个函数。通过一般属性实现父向子通信;通过函数属性实现子向父通信。
2.inheritAttrs
这是2.4.0新增的一个API,vue官网对于inheritAttrs的属性解释:如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs: false。
默认情况下父作用域的不被认作 props 的特性绑定将会回退且作为普通的HTML特性应用在子组件的根元素上。可通过设置 inheritAttrs 为 false,这些默认行为将会被去掉。注意:这个选项不影响class和 style绑定。
上个例中,title属性没有在子组件中props中声明,就会默认挂在子组件的根元素上,如下图所示:

如果在子组件设置:inheritAttrs: fasle,

3. data与props区别
-
相同点
两者选项里都可以存放各种类型的数据,当行为操作改变时,所有行为操作所用到和模板所渲染的数据同时都会发生同步变化。 -
不同点
data 被称之为动态数据,在各自实例中,在任何情况下,我们都可以随意改变它的数据类型和数据结构,不会被任何环境所影响。
props 被称之为静态数据,在各自实例中,一旦在初始化被定义好类型时,基于 Vue 是单向数据流,在数据传递时始终不能改变它的数据类型,而且不允许在子组件中直接操作 传递过来的props数据,而是需要通过别的手段,改变传递源中的数据。至于如何改变,我们接下去详细介绍:
4.单向数据流
这个概念出现在组件通信。props的数据都是通过父组件或者更高层级的组件数据或者字面量的方式进行传递的,不允许直接操作改变各自实例中的props数据,而是需要通过别的手段,改变传递源中的数据。那如果有时候我们想修改传递过来的prop,有哪些办法呢?
- 方法1:过渡到 data 选项中
在子组件的 data 中拷贝一份 prop,data 是可以修改的
export default {
props: {
type: String
},
data() {
return {
currentType: this.type
}
}
}
在 data 选项里通过currentType接收 props中type数据,相当于对 currentType= type进行一个赋值操作,不仅拿到了 currentType的数据,而且也可以改变currentType数据。
- 方法2:利用计算属性
export default {
props: {
type: String
},
computed: {
normalizedType: function () {
return this.type.toUpperCase();
}
}
}
以上两种方法虽可以在子组件间接修改props的值,但如果子组件想修改数据并且同步更新到父组件,却无济于事。在一些情况下,我们可能会需要对一个prop进行 双向绑定,此时就推荐以下这两种方法:
// 父组件
<template>
<div class="hello">
<div>
<p>父组件msg:{{ msg }}</p>
<p>父组件数组:{{ arr }}</p>
</div>
<button @click="show = true">打开model框</button>
<br/>
<demo :show.sync="show" :msg.sync="msg" :arr="arr"></demo>
</div>
</template>
<script>
import Demo from "./demo.vue"
export default {
name: "Hello",
components: {
Demo
},
data() {
return {
show: false,
msg: "模拟一个model框",
arr: [1, 2, 3]
}
}
}
</script>
// 子组件
<template>
<div v-if="show" class="border">
<div>子组件msg:{{ msg }}</div>
<div>子组件数组:{{ arr }}</div>
<button @click="closeModel">关闭model框</button>
<button @click="$emit('update:msg', '做梦跳绳闪到腰')">
改变文字
</button>
<button @click="arr.push('前端小胖')">改变数组</button>
</div>
</template>
<script>
export default {
props: {
msg: {
type: String
},
show: {
type: Boolean
},
arr: {
type: Array //在子组件中改变传递过来数组将会影响到父组件的状态
}
},
methods: {
closeModel() {
this.$emit("update:show", false)
}
}
}
网友评论