Vue js 组件详解与实战技巧(三)

Vue.js 是一款流行的前端框架,其组件化的设计使得开发者能够轻松构建复杂的用户界面。本文将详细介绍 Vue.js 中的组件概念,包括全局组件、局部组件、Prop 传递、自定义事件以及 v-model 的使用。通过这些知识点,你将能够更好地理解和运用 Vue.js 组件,提升开发效率。

什么是组件?

组件是 Vue.js 中最强大的功能之一。它可以扩展 HTML 元素,封装可重用的代码,使开发者能够用独立且可复用的小组件来构建大型应用。几乎任何类型的应用界面都可以抽象为一个组件树。

全局组件

全局组件是所有 Vue 实例都能使用的组件。注册全局组件的语法如下:

Vue.component(tagName, options)

其中,tagName 是组件名,options 是配置选项。注册后,可以通过以下方式调用组件:


<tagName></tagName>

全局组件实例

下面是一个简单的全局组件示例,我们将创建一个名为 runoob 的组件并使用它:

<div id="app">

<runoob></runoob>
</div><script>
  // 注册组件
  Vue.component('runoob', {
    template: '
<h1>自定义组件!</h1>'
  });

  // 创建根实例
  new Vue({
    el: '#app'
  });
</script>

局部组件

局部组件仅在特定的 Vue 实例中可用。我们可以在实例选项中注册局部组件,这样组件只能在这个实例中使用。

局部组件实例

下面是一个简单的局部组件示例,我们将创建一个名为 runoob 的局部组件并使用它:

<div id="app">

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

  // 创建根实例
  new Vue({
    el: '#app',
    components: {
      'runoob': Child
    }
  });
</script>

Prop 传递

Prop 是子组件用来接收父组件传递的数据的一种自定义属性。父组件的数据需要通过 props 传递给子组件,子组件需要显式地用 props 选项声明这些属性。

Prop 实例

下面是一个简单的 Prop 传递示例:

<div id="app">
  <child message="hello!"></child>
</div><script>
  // 注册组件
  Vue.component('child', {
    // 声明 props
    props: ['message'],
    // 在模板中使用 this.message
    template: '<span>{{ message }}</span>'
  });

  // 创建根实例
  new Vue({
    el: '#app'
  });
</script>

动态 Prop

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

动态 Prop 实例

下面是一个动态 Prop 的示例:

<div id="app">

<div>
    <input v-model="parentMsg">
    <br>
    <child v-bind:message="parentMsg"></child>
  </div>
</div><script>
  // 注册组件
  Vue.component('child', {
    // 声明 props
    props: ['message'],
    // 在模板中使用 this.message
    template: '<span>{{ message }}</span>'
  });

  // 创建根实例
  new Vue({
    el: '#app',
    data: {
      parentMsg: '父组件内容'
    }
  });
</script>

Prop 验证

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

Prop 验证实例

下面是一个 Prop 验证的示例:

Vue.component('my-component', {
  props: {
    // 基础的类型检查
    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'].includes(value);
      }
    }
  }
});

自定义事件

父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件。Vue 提供了 $on 和 $emit 方法来实现这一功能。

自定义事件实例

下面是一个自定义事件的示例:

<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>

自定义组件的 v-model

组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。这使得我们可以像使用原生输入元素一样使用自定义组件。

自定义组件的 v-model 实例

下面是一个自定义组件的 v-model 示例:

<div id="app">
  <runoob-input v-model="num"></runoob-input>

<p>输入的数字为:{{ num }}</p>
</div><script>
  Vue.component('runoob-input', {
    template: `

<p>
        <input
          ref="input"
          :value="value"
          @input="$emit('input', $event.target.value)"
        >
      </p>
    `,
    props: ['value']
  });

  new Vue({
    el: '#app',
    data: {
      num: 100
    }
  });
</script>

对于复选框或单选框的组件,我们需要使用 model 选项来指定当前的事件类型和传入的 props。

复选框组件的 v-model 实例

下面是一个复选框组件的 v-model 示例:

<div id="app">
  <base-checkbox v-model="lovingVue"></base-checkbox>
  <div v-show="lovingVue">如果选择框打勾我就会显示。</div>
</div><script>
  Vue.component('base-checkbox', {
    model: {
      prop: 'checked',
      event: 'change'
    },
    props: {
      checked: Boolean
    },
    template: `
      <input
        type="checkbox"
        :checked="checked"
        @change="$emit('change', $event.target.checked)"
      >
    `
  });

  new Vue({
    el: '#app',
    data: {
      lovingVue: true
    }
  });
</script>

自定义指令

Vue 允许注册自定义指令,这些指令可以用于增强元素的行为。自定义指令可以通过 Vue.directive 注册为全局指令,也可以在实例中通过 directives 选项注册为局部指令。

全局自定义指令实例

下面是一个全局自定义指令的示例,该指令的功能是在页面加载时,元素自动获取焦点:

<div id="app">

<p>页面载入时,input 元素自动获取焦点:</p>
  <input v-focus>
</div><script>
  // 注册全局自定义指令
  Vue.directive('focus', {
    inserted: function (el) {
      el.focus();
    }
  });

  new Vue({
    el: '#app'
  });
</script>

局部自定义指令实例

下面是一个局部自定义指令的示例,该指令同样在页面加载时,元素自动获取焦点:

<div id="app">

<p>页面载入时,input 元素自动获取焦点:</p>
  <input v-focus>
</div><script>
  new Vue({
    el: '#app',
    directives: {
      focus: {
        inserted: function (el) {
          el.focus();
        }
      }
    }
  });
</script>

钩子函数

指令定义函数提供了几个钩子函数,这些钩子函数在不同的生命周期阶段被调用:

  • bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
  • inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于文档中)。
  • update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的更新。

总结

通过本文的介绍,你应该对 Vue.js 中的组件有了更深入的理解。无论是全局组件还是局部组件,Prop 传递、自定义事件、v-model 以及自定义指令,都是构建复杂应用不可或缺的部分。希望这些知识能够帮助你在项目中更好地使用 Vue.js,提高开发效率。如果你有任何疑问或建议,欢迎在评论区留言交流。