美文网首页
Vue中的props理解

Vue中的props理解

作者: 北雁南飞_8854 | 来源:发表于2021-01-16 20:54 被阅读0次

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:

  1. 定义props为一个string数组,数组中的每一个元素对应一个props名字;
  2. 定义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}}&nbsp--&nbsp 年龄:{{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(短横线隔开) 的事件名。

相关文章

网友评论

      本文标题:Vue中的props理解

      本文链接:https://www.haomeiwen.com/subject/wpkoaktx.html