Vue之组件(组件细节、模块系统、v-model语法糖)

前言

  • 本节针对组件应用相关细节做下补充,以便查漏补缺,大纲如下
    (1)H5编码规范与template模板的3种写法
    (2)组件data
    (3)组件名
    (4)组件注册
    (5)模块系统(需结合后续工程化使用,这里简单了解即可)
    (6)自定义事件(父子组件通信)
    (7).sync修饰符
    (8)自定义组件之v-model语法糖

H5编码规范

  • 分析如下代码中的组件解析结果
    Vue之组件(组件细节、模块系统、v-model语法糖)_第1张图片
    Vue之组件(组件细节、模块系统、v-model语法糖)_第2张图片

  • H5规范中要求,table里为tbody,tbody里需要放置tr和td,否则会将代码解析到table外。

  • 方案:

    • 这里,tbody中放置的是row,所以会解析到table同级外部,解决方案为is属性。既然tbody里只能放置tr,那么这里便改成tr+is属性
      Vue之组件(组件细节、模块系统、v-model语法糖)_第3张图片
      在这里插入图片描述
      此时即保证tr里显示的为组件,又可以保证H5的编码规范。同理还有ul→li、select→option等等。

template组件模板写法

  • 写法一:直接写在选项里的模板
  • 直接在构造器里的template选项后边编写。这种写法比较直观,但是如果模板html代码太多,不建议这么写。
    Vue之组件(组件细节、模块系统、v-model语法糖)_第4张图片
    这里需要注意的是模板的标识不是单引号和双引号,而是,就是Tab上面的键
  • 写法二:写在template标签里的模板
  • 这种写法更像是在写HTML代码,就算不会写Vue的人,也可以制作页面。
    Vue之组件(组件细节、模块系统、v-model语法糖)_第5张图片
  • 写法三:写在script标签text/x-template里的模板
  • 这种写模板的方法,可以让模板文件从外部引入。
    Vue之组件(组件细节、模块系统、v-model语法糖)_第6张图片
  • 小结:
    写法一:直接写在选项里的模板
    写法二:写在template标签里的模板
    写法三:写在script标签里的模板
  • 这里介绍了template的三种写法,以后学习到vue-cli的时候还会学到一种xxx.vue的单文件组件写法。

组件data

  • 在使用 data 和实例稍有区别, 组件的data必须是函数,且必须将数据 return出去。
  • 案例:
    Vue之组件(组件细节、模块系统、v-model语法糖)_第7张图片
    在这里插入图片描述
    1、组件的data必须为函数且返回值
    2、返回值不能引用外部对象,每次需要返回一个新的data 对象来独立

组件名

  • 在注册一个组件的时候,始终需要给它一个名字。比如在全局注册的时候,该组件名就是 Vue.component 的第一个参数
    在这里插入图片描述
  • 注意:
  • (1)命名注意==“语义化”==:即你给予组件的名字可能依赖于你打算拿它来做什么
  • (2)定义组件名的方式3种
  • 组件注册
    • 为了能在模板中使用,组件必须先注册以便 Vue 能够识别。Vue有两种组件的注册类型:全局注册和局部注册。
  • (1)全局注册
    在这里插入图片描述
  • 全局注册的组件,在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。如下所示:
    Vue之组件(组件细节、模块系统、v-model语法糖)_第8张图片
    Vue之组件(组件细节、模块系统、v-model语法糖)_第9张图片
  • 全局组件“嵌套性”:在所有子组件中也是如此,也就是说这三个组件在各自内部也都可以相互使用。
  • (2)局部注册
    • 缘由:全局注册往往是不够理想的,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的JS的无谓的增加。
  • 在这些情况下,你可以通过一个普通的 JS对象来定义组件。
    Vue之组件(组件细节、模块系统、v-model语法糖)_第10张图片
  • 如上所示使用JS对象定义好组件对象,然后在 components 选项中定义你想要使用的组件
    Vue之组件(组件细节、模块系统、v-model语法糖)_第11张图片
  • 对于 components 对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
  • (2)局部组件局限
  • 局部注册的组件在其子组件中不可用。
  • 例如:如果你希望 ComponentA 在 ComponentB 中可用,则需要这样写
    Vue之组件(组件细节、模块系统、v-model语法糖)_第12张图片
  • 或者如果通过 Babel 和 webpack 使用 ES2015 即ES6 模块,那么代码如下所示:
  • (2)局部注册—简单了解即可
    Vue之组件(组件细节、模块系统、v-model语法糖)_第13张图片
  • 在 ES2015+ 中,在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写,即这个变量名同时是:
    ①用在模板中的自定义元素的名称
    ②包含了这个组件选项的变量名

模块系统

  • 简单了解,后期工程化详细介绍使用。
  • (1)在模块系统中局部注册
  • 工程化完毕后,在项目下创建一个 components
    组件目录,并将每个组件放置在其各自的文件中。然后需要在局部注册之前导入每个想使用的组件。例如,在一个假设的 ComponentB.js 或
    ComponentB.vue 文件中:
    Vue之组件(组件细节、模块系统、v-model语法糖)_第14张图片
    在这里插入图片描述
    此时,ComponentA 和 ComponentC 都可以在 ComponentB 的模板中使用了
  • (2)基础组件的自动化全局注册
  • 可能你的许多组件只是包裹了一个输入框或按钮之类的元素,是相对通用的。我们会把它们称为基础组件,它们会在各个组件中被频繁的用到。所以会导致很多组件里都会有一个包含基础组件的长列表,如下所示
    Vue之组件(组件细节、模块系统、v-model语法糖)_第15张图片
  • (2)基础组件的自动化全局注册
    • 如果使用了 webpack (或在内部使用了 webpack 的 Vue Cli 3+),那么就可以使用 require.context 只全局注册这些非常通用的基础组件。
    • 在应用入口文件 (比如 src/main.js) 中全局导入基础组件的示例代码,如下所示:
      Vue之组件(组件细节、模块系统、v-model语法糖)_第16张图片
      在这里插入图片描述
      Vue之组件(组件细节、模块系统、v-model语法糖)_第17张图片
  • 正如之前所讲,子组件→父组件
    • 当子组件需要向父组件传递数据时,需要用到自定义事件。
    • Vue 组件有一套观察者模式,子组件用 e m i t ( ) 来 触 发 事 件 , 父 组 件 用 emit()来触发事件,父组件用 emit()on()来监听子组件的事件
  • 语法结构:
    • 父组件通过v-on:eventName="parentEventName"来设置监听
    • 子组件通过$.emit(‘eventName’)来触发事件。

自定义事件

  • 自定义事件案例:
    (1)子组件触发事件$.emit(‘eventName’,option)

Vue之组件(组件细节、模块系统、v-model语法糖)_第18张图片

  • 自定义事件案例:
    (2)父组件设置监听v-on:eventName="parentEventName"并接收参数
    Vue之组件(组件细节、模块系统、v-model语法糖)_第19张图片
  • 自定义事件之事件名:
    • 不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称。举个例子,如果触发一个 camelCase 名字的事件:
this.$emit('myEvent')
  • 则监听这个名字的 kebab-case 版本是不会有任何效果的


自定义事件-事件名

  • 注意:
  • 不同于组件和 prop,事件名不会被用作一个 JavaScript 变量名或属性名,所以就没有理由使用 camelCase 或 PascalCase 了。
  • 并且 v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent 将会变成 v-on:myevent——导致 myEvent 不可能被监听到。
  • 推荐:
  • 综上所述,对于自定义事件名,建议始终使用 kebab-case 短横线命名法

.sync修饰符

  • 前言:
  • 在vue2.4以前,父组件向子组件传值用props;子组件不能直接更改父组件传入的值,需要通过$emit触发自定义事件,通知父组件改变后的值,如此才能实现父子组件的通信。
  • 过程比较繁琐,写法如下:
    Vue之组件(组件细节、模块系统、v-model语法糖)_第20张图片
  • .sync修饰符:
  • vue2.4以后的写法明显舒服许多,上面同样的功能,直接上代码
    Vue之组件(组件细节、模块系统、v-model语法糖)_第21张图片
  • 写法上简化了一部分,很明显父组件不用再定义方法检测值变化了。其实只是对以前的$emit方式的一种缩写,.sync其实就是在父组件定义了一update:value方法,来监听子组件修改值的事件。

v-model语法糖

首先来回顾下v-model相关知识点。

  • (1)v-model指令是什么?

    • vue通过v-model实现双向绑定数据,所以首先我们要明白v-model在这个过程中做了什么。
  • (2)v-model指令本质?

    • 有vue基础的同学应该知道,v-model本质是一个语法糖。 即v-bind和v-on的结合体。
  • (3)v-model本质验证

    • 表单元素比如input,v-bind绑定一个值,就把data数据传给了value,同时再通过v-on监听input事件,当表单数据改变的时候,也会把值传给data数据,代码如下
      Vue之组件(组件细节、模块系统、v-model语法糖)_第22张图片
      在这里插入图片描述
      Vue之组件(组件细节、模块系统、v-model语法糖)_第23张图片
  • (4)v-model等效写法

    • 综上所述,v-model为v-on和v-bind结合体
      在这里插入图片描述
  • 前言:
    在日常开发中,自定义一个支持双向绑定的组件是非常常见的应用场景,而官方文档中对于自定义组件如何实现v-model双向绑定的描述几近于0。那么,怎样实现一个自定义组件v-model,就是本篇将要介绍的内容。

  • 官方文档:

    • 允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把
      value 用作 prop 且把 input 用作 event
      ,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop
      来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。
    • 上面,这句话比较长,咱们来一步步理解,首先是第一句------允许一个自定义组件在使用v-model时定制prop和event 一般说来,v-model用在表单元素上进行数据的双向绑定,自定义组件通常通过父子组件传值绑定数据------默认情况下,一个组件上的v-model会把value用作prop且把input用作event。
    • 前边说了,v-model是v-bind和v-on的语法糖,那么这里v-model就完成两个步骤,接下来举个例子
  • 案例1:组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件
    Vue之组件(组件细节、模块系统、v-model语法糖)_第24张图片
    上图:此时便可以实现组件v-model数据双向绑定
    ①默认prop传值为value
    ②默认event事件为input

  • 上述代码中父组件的v-model相当于v-on+v-bind写法结合,如下

Vue之组件(组件细节、模块系统、v-model语法糖)_第25张图片
上图初始值为num,绑定$emit返回事件名input,两者相加的效果等价于v-model

  • 父级方法接收返回值,更新数据
    Vue之组件(组件细节、模块系统、v-model语法糖)_第26张图片
  • 代码解析:
  • 前面说了,父子组件传值通过prop和$emit
    • 第一步:父组件把num通过prop传给了子组件,但要注意,这里的子组件可以给prop取了一个别名,例如叫做value作为区分,所以子组件的props对象中的键为取的别名value。如果没有设置别名,则直接使用即可
    • 第二步:当子组件input值改变的时候,子组件监听了一个oninput方法,注意这里也给 e m i t 中 的 事 件 取 了 一 个 别 名 , 只 不 过 这 个 别 名 和 原 来 的 名 字 一 样 o n i n p u t , i n p u t 值 改 变 后 , 通 过 emit中的事件取了一个别名,只不过这个别名和原来的名字一样oninput,input值改变后,通过 emitoninputinputemit提交input事件并把新值传给父组件,又要注意->$emit的荷载为字符串
  • 官方解析:
    • v-model用在自定义组件最大的好处是提高了组件的封装性,父组件不必要另外写一个接受子组件发送给来的$emit方法。
    • 最后是第三句话,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的. —其实这很容易理解,因为value字符串在input中是有意义的,取别名有利于区分…
  • 案例2:对上述案例做下调整,修改事件类型event为blur失焦时触发,代码如下
    Vue之组件(组件细节、模块系统、v-model语法糖)_第27张图片
    此时,不再是实时输入触发数据更新,而是输入框失焦时更新数据
  • 案例3:
  • 正如官方文档所说:像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的,model 选项可以用来避免这样的冲突。
  • 接下来修改model默认项,如下所示
    Vue之组件(组件细节、模块系统、v-model语法糖)_第28张图片
    这里的 checkStatus 的值将会传入这个名为 checked 的 prop。同时当 触发一个 change 事件并附带一个新的值的时候,这个 checkStatus的属性将会被更新。

总结

  • 1、v-model是v-bind:value和v-on:input的简写
  • 2、H5编码规范中要求,部分标签的嵌套结构必须固定(例如:table里为tbody,tbody里需要放置tr和td,否则会将代码解析到table外)
  • 3、不同于组件和 prop,事件名$emit(事件)不存在任何自动化的大小写转换,必须短横线
  • 4、组件名语义化:命名注意“语义化”,即你给予组件的名字可能依赖于你打算拿它来做什么

完毕…

你可能感兴趣的:(Vue,日报,JavaScript)