vue成长之路+实战+Vue2+VueRouter2+webpack(二)vue组件入门第一节

推荐我的vue教程:VUE系列教程目录

上篇讲解了vue-router路由入门,现在讲讲关于vue组件的内容。
如果你们有使用过element组件的话,他就是以vue组件的形式进行封装的,在讲解组件之前我们需要知道vue是数据驱动的,它的一切依赖于数据,我们应该根据数据的不同来进行相关的处理,在这一前提下才能形成vue框架的思考模式。
在了解这一模式的前提下我们来看看vue组件是个什么东西。

什么是VUE组件?

在github上,各位请使用git拉一下项目:vuetemplate。不会使用git拉文件的请去GitHub上下载压缩包。

/src/page/components下是有关组件的代码

我们打开vue官网的组件API,可以简单浏览,对于新手来说这个API的阅读有时很晦涩,或者跟实际应用有些许差别。于是我的讲解是建立在对这个API的补充说明与简单化的,所以你们最好还是看看这个。

VUE组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,VUE组件是自定义元素, Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。

注册组件

在注册组件时我们有两种方式,第一种注册全局组件,第二种是局部使用组件,对于那些应用多的组件来说全局无疑是最好的选择,对于变数太大,应用不多且在统一目录下的局部使用是我们想要的。

全局注册:

要注册一个全局组件,你可以使用 Vue.component(tagName, options)。

// 模板
Vue.component('my-component', {
  // 选项
})

一个模板并不能说明什么,实例才能让人看的更明白:

// html


// 注册
Vue.component('my-component', {
  template: '
A custom component!
' })

组件的简单使用就是这个样子,即最后变成了

A custom component!
。可是,实际操作中我们并不会这么弱智的使用,组件的复杂度远远不是这个样子的。

局部注册

要注册一个局部组件,你可以使用 Vue的components属性。


例子才是真理:

// html



DOM渲染的局限

在html中我们知道有些标签的孩子是固定的比如

      , ,
      ...

      自定义组件 被认为是无效的内容,因此在渲染的时候会导致错误。那我们怎么解决呢?变通的方案是使用特殊的 is 属性:

      data 必须是函数

      组件中必须是函数,通过Vue构造器传入的各种选项大多数都可以在组件里用。 data 是一个例外,它必须是函数。

      // html
      
      
      
      

      这里有很多人看蒙了,问起初不是这样写吗???

      data: {
          counter: 0
      }
      

      这里别问,我起初也没看懂,你可以这样想:把所有关于data的数据引入变为data () {}就可以了。
      为何我会这样说?我曾经在上一篇文章里说:vue路由的本质是根据url的不同来进行组件的各种切换罢了。而组件的data必须是数据,所以你看我写的代码里关于.vue文件的都使用的是这种结构:

      
      
      

      如果不明白你可以看上面的组件的例子,其最终的本质变成了:

      
      
      

      其实你只要使用vue-router路由你的.vue文件的结构只能变成这样:

      
      
      

      构成组件

      组件意味着协同工作,引用组件的地方叫父组件,如,组件的内容则被成为子组件。

      通常父子组件会是这样的关系:组件 A 在它的模版中使用了组件 B 。它们之间必然需要相互通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。然而,在一个良好定义的接口中尽可能将父子组件解耦是很重要的。这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性。

      在 Vue.js 中,父子组件的关系可以总结为 props down, events up 。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。看看它们是怎么工作的?如图:

      vue成长之路+实战+Vue2+VueRouter2+webpack(二)vue组件入门第一节_第1张图片
      父子组件数据交互

      父子组件的交互的原理这个具体呢?

      父子组件的交互

      props的单向流

      组件实例的作用域是孤立的。这意味着不能(也不应该)在子组件的模板内直接引用父组件的数据。要让子组件使用父组件的数据,我们需要通过子组件的props选项。

      我们在开发中,一个单文件组件的.vue文件的基本构成是这样的:

      
      
      
      

      可是常用的很少,父组件给子组件传值使用的就是props选项

      props选项可以接受两种模式的参数:

      第一种固定的属性:如这样message="hello!传一个普通的字符;
      第二种动态属性:如这样v-bind:myMessage="this.message"传一个变量,其可以简化为:myMessage="this.message"

      例子如下:(父子组件在同一目录下,子组件-child.vue)

      // 父组件
      // HTML
      
      
      // script
      
      
      
      
      // 子组件
      
      
      
      
      

      prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态。

      另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop 。如果你这么做了,Vue 会在控制台给出警告。

      但是有时我们就是需要修改,怎么办?(老子需求)

      一般情况下我们修改通常是这两种原因:

      1. prop 作为初始值传入后,子组件想把它当作局部数据来用;
      2. prop 作为初始值传入,由子组件处理成其它数据输出。

      对于第一种情况我们可以李代桃僵,即用另外一个变量替代它,把它的值赋给那个变量:

      data () { // 基础数据
          return {
            //
            counter: this.message
          }
        }
      

      第二种情况可以定义一个计算属性,处理 prop 的值并返回:

      computed: {
          messagetoLowerCase: function () {
            return this.message.trim().toLowerCase()
          }
      }
      
      注意:使用字面量语法传递数值时,必须使用动态props,即如这样`v-bind:number="1"`
      

      props验证

      我们可以为组件的 props 指定验证规格。如果传入的数据不符合规格,Vue 会发出警告。当组件给其他人使用时,这很有用。

      要指定验证规格,需要用对象的形式,而不能用字符串数组:(修改上面的例子)

      // html
      
      
      // 子组件props
      props: {
          message: String,
          myMessage: {
            type: String,
            required: true
          },
          number: {
            validator: function (value) {
              return value > 10
            }
          }
        }
      

      验证规格模板:

      props: {
          // 基础类型检测 (`null` 意思是任何类型都可以)
          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 value > 10
            }
          }
        }
      

      自定义事件向父组件传值

      事件$on与$emit

      我们知道,父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,应该怎样做?那就是自定义事件!

      每个 Vue 实例都实现了事件接口(Events interface),即:

      使用 $on(eventName) 监听事件
      使用 $emit(eventName) 触发事件

      注意:Vue的事件系统分离自浏览器的EventTarget API。尽管它们的运行类似,但是$on 和 $emit 不是addEventListener 和 dispatchEvent 的别名。

      你们一定很奇怪怎么用事件监听来向父元素传递?

      其实原理很简单就是我们在父组件上通过v-on监听子组件的事件,而子组件通过$emit(eventName) 触发事件。例子如下:

      // 父组件
      
      
      
      // 子组件
      
      
      
      
      

      这个例子中,子组件给父组件传值通过$emit('onchild'),触发父组件的v-on:onchildv-on:onchild响应后执行inparent函数。但是就达到我们的目的了???

      传值,传值,传值,值呢?这个API里可没说,那怎么办呢?

      很简单按照程序工程师的思路来想,值肯定是这种模式:

      this.$emit('onchild', 需要的值)
      // 多个呢?
      this.$emit('onchild', 需要的值1,需要的值2)
      

      那接值呢?

      onparent (需要的值1, 需要的值2) {
      }
      

      所以完整的模式应该是这样的:

      // 父组件
      
      
      
      // 子组件
      
      
      
      
      sync-修饰符

      在一些情况下,我们可能会需要对一个 prop 进行『双向绑定』。当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定的值。这很方便,但也会导致问题,因为它破坏了『单向数据流』的假设。由于子组件改变 prop 的代码和普通的状态改动代码毫无区别,当光看子组件的代码时,你完全不知道它何时悄悄地改变了父组件的状态。这在 debug 复杂结构的应用时会带来很高的维护成本。

      事实上,这正是 Vue 1.x 中的 .sync修饰符所提供的功能。但是VUE在 2.0 中移除了 .sync。后来在 2.3 VUE又重新引入了 .sync 修饰符。

      // 父组件
      
      
      
      // 子组件
      
      
      
      

      其实本质上VUE做到的只是:需要做的只是让子组件改变父组件状态的代码更容易被区分。

      即把简写为,不让使用者在父元素上进行事件监听了而已其他都是一样的,它通过子组件传值改变父组件,依赖props传值把修改的父组件元素再传回子组件而已。

      小结:

      父组件向子组件传值通过props;子组件向父组件传值,我们在父组件上通过v-on监听子组件的事件,而子组件通过$emit(eventName) 触发事件。

      至此组件的基本知识就结束了,高深的组件有关的,下一节再说。

      提示:在最近几天我会慢慢附上VUE系列教程的其他后续篇幅,后面还有精彩敬请期待,请大家关注我的专题:web前端。如有意见可以进行评论,每一条评论我都会认真对待。

你可能感兴趣的:(vue成长之路+实战+Vue2+VueRouter2+webpack(二)vue组件入门第一节)