Vue中的props理解
2021-01-16 本文已影响0人
北雁南飞_8854
Vue组件
Vue实例中的data属性是一个对象,然而组件中的data属性是一个函数。这是因为一个组件可以在同一个页面上被多次引用,你大概不希望他们共享一个data对象(因为同一个组件的每个实例的data属性是同一个对象的引用,当该组件的某个实例修改了自身的data属性,相当于所有组件的data属性都被修改了。)所以组件的data属性应该是一个函数,在组件初始化是Vue会调用这个函数来生成data对象。
方式一
App.vue
<template>
<div id="app">
<display-number v-bind:number="number"></display-number>
</div>
</template>
<script>
import Vue from "vue";
Vue.component("DisplayNumber", {
template: `<p>当前数字是{{number}}</p>`,
props: {
number: {
type: Number,
required: true,
},
},
created() {
setInterval(() => {
this.number++;
}, 1000);
},
});
export default {
name: "App",
data() {
return {
number: 0,
};
},
};
</script>
方式二
DisplayNumber.vue
<template>
<div class="DisplayNumber">
<p>当前数字是{{ number }}</p>
</div>
</template>
<script>
export default {
name: "DisplayNumber",
props: {
number: {
type: Number,
required: true,
},
},
created() {
setInterval(() => {
this.number++;
}, 1000);
},
};
</script>
App.vue
<template>
<div id="app">
<display-number v-bind:number="number"></display-number>
</div>
</template>
<script>
import DisplayNumber from "@/components/DisplayNumber";
export default {
name: "App",
data() {
return {
number: 0,
};
},
components: {
DisplayNumber
}
};
</script>
再看另外一个例子:
App.vue
<template>
<div id="app">
<demo-key
v-for="(item, index) in items"
:key="item"
@click.native="items.splice(index, 1)"
>
{{ item }}
</demo-key>
</div>
</template>
<script>
const randomColor = () => {
return `hsl(${Math.floor(Math.random() * 360)}, 75%, 85%)`;
};
const DemoKey = {
template: `<p :style="{backgroundColor: color}"><slot></slot></p>`,
data: () => ({ color: randomColor() }),
};
export default {
name: "App",
data() {
return {
items: ["one", "two", "three", "four", "five"],
};
},
components: {
DemoKey,
},
};
</script>
结果:
image.png
Style的使用
DisplayNumber.vue
<template>
<div class="DisplayNumber">
<p>
当前数字是<span class="number">{{ number }}</span>
</p>
</div>
</template>
<script>
export default {
name: "DisplayNumber",
props: {
number: {
type: Number,
required: true,
},
},
created() {
setInterval(() => {
this.number++;
}, 1000);
},
};
</script>
<style>
.number {
font-weight: bold;
}
</style>
注册props:
- 定义props为一个string数组,数组中的每一个元素对应一个props名字;
- 定义props为一个object,每一个key对应一个props名字。
props为单向的数据绑定。一个component永远不要修改它自己的props。原因是,这会使调试难度增加,如果某个value传给了它的多个children组件,很难跟踪到这个值的变化来自哪里。另外,改变props会导致该组件被重复刷新。
组件中的data属性是一个function,而不是object;
data属性不要使用箭头函数(arrow function)。
v-bind
将Javascript表达式(Javascript expression)和HTML 元素和组件(HTML elements and components)绑定起来。
v-bind:attribute="expression"
在大多数时候,可以简写为:
:attribute="expression"
看例子:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
<div id="app">
<!-- 将parent-component的children-dataset属性和Vue实例的childrenData属性绑定到一起。-->
<parent-component v-bind:children-dataset="childrenData"></parent-component>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
//创建一个component组件。(可以命名为parent-component,也可以是parentComponent,效果一样。但是在div中必须使用parent-component)。
Vue.component('parentComponent', {
//父组件将数据传到子组件,props命名可以是children-dataset,也可以是childrenDataset,但是div中使用时必须使用children-dataset.
props: ["childrenDataset"],
//一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝.
data: function () {
return {
text: "Parent初始数据",
postFontSize: 1
};
},
template:
`<div :style="{ fontSize: postFontSize + 'em' }">
<p >{{text}}</p>
<children-component v-bind:content-list="childrenDataset" v-on:enlarge-text="onEnlargeText">
</children-component>
</div>`,
methods: {
onEnlargeText: function (item, enlargeAmount) {
this.text = item.name;
this.postFontSize += enlargeAmount
}
}
})
Vue.component('childrenComponent', {
props: ['contentList'],
template:
`<ul>
<li v-for="item in contentList" v-on:click="onClick(item)">
名字:{{item.name}} --  年龄:{{item.age}}
</li>
</ul>`,
methods: {
onClick: function (item) {
//通过调用内建的$emit方法并传入事件名称来触发一个事件.
this.$emit("enlarge-text", item, 0.1);
}
}
})
new Vue({
el: '#app',
data: {
childrenData: [
{
name: 'Bob',
age: 25
},
{
name: 'Chris',
age: 26
},
{
name: 'David',
age: 27
},
{
name: 'Ella',
age: 28
}
],
postFontSize: 1
}
})
</script>
</body>
</html>
Prop 的大小写 (camelCase vs kebab-case)
HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名。
在HTML中通过kebab-case形式指定的属性,会在组件内部自动转换为camelCase 形式。我们不需要作任何额外的处理,这种转换会自动完成。
<template>
<div id="app">
<h1>To-Do List</h1>
<ul>
<li>
<!-- 在 HTML 中是 kebab-case 的 -->
<to-do-item></to-do-item>
</li>
</ul>
</div>
</<template>
<script>
//在 JavaScript 中是 camelCase(驼峰命名法) 的
import ToDoItem from "./components/ToDoItem.vue";
export default {
name: "App",
components: {
ToDoItem
}
}
</script>
自定义事件
官方推荐,始终使用 kebab-case(短横线隔开) 的事件名。