Vue.js组件

作者: InFatuated | 来源:发表于2020-10-13 13:50 被阅读0次

组件(Component)是Vue.js最强大的功能之一。
组件可以扩展HTML元素,封装可重用的代码。
组件系统让我们可以独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:



注册一个全局组件语法格式如下:

Vue.component(tagName,options)

tagName为组件名,options为配置选项。注册后,我们可以使用以下方式来调用组件:

<tagName></tagName>

全局组件

所有实例都能用全局组件
全局组件上架
注册一个简单的全局组件runoob,并使用它:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
    <runoob></runoob>
</div>

<script>
// 注册
Vue.component('runoob', {
  template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({
  el: '#app'
})
</script>
</body>
</html>

局部组件

我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:
局部组件实例
注册一个简单的局部组件runoob,并使用它:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
    <runoob></runoob>
</div>

<script>
var Child = {
  template: '<h1>自定义组件!</h1>'
}

// 创建根实例
new Vue({
  el: '#app',
  components: {
    // <runoob> 将只在父模板可用
    'runoob': Child
  }
})
</script>
</body>
</html>

Prop

prop是子组件用来接受父组件传递过来的数据的一个自定义属性。
父组件的数据是通过props把数据传给子组件,子组件需要显式地用props选项声明"prop":
Prop实例

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
    <child message="hello!"></child>
</div>

<script>
// 注册
Vue.component('child', {
  // 声明 props
  props: ['message'],
  // 同样也可以在 vm 实例中像 “this.message” 这样使用
  template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
  el: '#app'
})
</script>
</body>
</html>

动态Prop

类似于用v-bind绑定HTML特性到一个表达式,也可以用v-bind动态绑定props的值父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
Prop实例

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
    <div>
      <input v-model="parentMsg">
      <br>
      <child v-bind:message="parentMsg"></child>
    </div>
</div>

<script>
// 注册
Vue.component('child', {
  // 声明 props
  props: ['message'],
  // 同样也可以在 vm 实例中像 “this.message” 这样使用
  template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
  el: '#app',
  data: {
    parentMsg: '父组件内容'
  }
})
</script>
</body>
</html>

以下实例中使用v-bind指令将todo传到每一个重复的组件中:
Prop实例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
    <ol>
    <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
    </ol>
</div>

<script>
Vue.component('todo-item', {
  props: ['todo'],
  template: '<li>{{ todo.text }}</li>'
})
new Vue({
  el: '#app',
  data: {
    sites: [
      { text: 'Runoob' },
      { text: 'Google' },
      { text: 'Taobao' }
    ]
  }
})
</script>
</body>
</html>

注意:prop是单向绑定的:当父组件的属性变化,将传导给子组件,但是不会反过来。

Prop验证

组件可以为props指定验证要求。
为了定制prop的验证方式,你可以为props中的值提供一个带有验证需求的对象,而不是一个字符数组。例如:

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

当prop验证失败的时候,(开发环境构建的版本的)Vue将会产生一个控制台的警告。
type可以是下面原生构造器:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol
    type也可以是一个定义构造器,使用instanceof检测。

自定义事件

父组件是使用props传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我么可以使用v-on绑定自定义事件,每个Vue实例都实现了事件接口(Events interface),即:

  • 使用$on(eventName)监听事件
  • 使用$emit(eventName)触发事件
    另外,父组件可以在使用子组件的地方直接用v-on来监听子组件触发的事件。
    以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。
    实例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
    <div id="counter-event-example">
      <p>{{ total }}</p>
      <button-counter v-on:increment="incrementTotal"></button-counter>
      <button-counter v-on:increment="incrementTotal"></button-counter>
    </div>
</div>

<script>
Vue.component('button-counter', {
  template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    incrementHandler: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})
new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})
</script>
</body>
</html>

如果你想在某个组件的根元素上监听一个原生事件。可以使用.native修饰v-on。例如:

<my-component v-on:click.native="doTheThing"></my-component>

data必须是一个函数

上面例子中,可以看到button-counter组件中的data不是一个对象,而是一个函数:

data: function () {
  return {
    count: 0
  }
}

这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝,如果data是一个对象则会影响到其他实例,如下所示:
实例

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="components-demo3" class="demo">
    <button-counter2></button-counter2>
    <button-counter2></button-counter2>
    <button-counter2></button-counter2>
</div>

<script>
var buttonCounter2Data = {
  count: 0
}
Vue.component('button-counter2', {
    /*
    data: function () {
        // data 选项是一个函数,组件不相互影响
        return {
            count: 0
        }
    },
    */
    data: function () {
        // data 选项是一个对象,会影响到其他实例
        return buttonCounter2Data
    },
    template: '<button v-on:click="count++">点击了 {{ count }} 次。</button>'
})
new Vue({ el: '#components-demo3' })
</script>
</body>
</html>

相关文章

网友评论

    本文标题:Vue.js组件

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