Vue进阶(一)|青训营笔记

60 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第7天

本文主要是对Vue中的一些进阶知识进行学习记录,对基础的概念不作详解。

组件注册

组件名称

一般采用两种方式

kebab-casemy-component-a

PascalCase:MyComponentA

组件注册

局部注册
var ComponentA = { /* ... */ }//创建一个组件对象
​
​
new Vue({
 el'#app',
 components: {
   'component-a': ComponentA,
   'component-b': ComponentB
}
})
在模块系统中局部注册
//ComponentB.js
import ComponentA from './ComponentA'
import ComponentC from './ComponentC'export default {
 components: {
   ComponentA,
   ComponentC
},
 // ...
}

Prop

名称规范

jsvue 文件的模版(template)中,使用驼峰命名法,然而在HTML中需要使用短横线分隔 。这是因为HTML 对大小写不敏感。

类型
props: {
 titleString,
 likesNumber,
 isPublishedBoolean,
 commentIdsArray,
 authorObject,
 callbackFunction,
 contactsPromisePromise // or any other constructor
}

传入所有对象

如果一个对象中属性很多,写起来会很复杂,可以使用语法

v-bind = "xxx",这样就可以一下子传入xxx 具有的所有参数。

单向数据流

ReactProp 一样,父传给子的数据不允许被修改,这是利于维护的。要修改可以变为组件自身的data,这像是React 中的State

验证

可以在传入prop时进行验证,若不符合要求控制台会进行警告。

Vue.component('my-component', {
 props: {
   // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
   propANumber,
   // 多个可能的类型
   propB: [StringNumber],
   // 必填的字符串
   propC: {
     typeString,
     requiredtrue
  },
   // 带有默认值的数字
   propD: {
     typeNumber,
     default100
  },
   // 带有默认值的对象
   propE: {
     typeObject,
     // 对象或数组默认值必须从一个工厂函数获取
     defaultfunction () {
       return { message'hello' }
    }
  },
   // 自定义验证函数
   propF: {
     validatorfunction (value) {
       // 这个值必须匹配下列字符串中的一个
       return ['success''warning''danger'].includes(value)
    }
  }
}
})
类型检查

type可能存在的值:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol
  • 自定义函数

自定义函数例如:

function Person (firstName, lastName) {
 this.firstName = firstName
 this.lastName = lastName
}

非prop属性

指没有显示声明prop的属性。这种时候,属性会自动被添加到组件的根元素上。

自动合并

若原来已经存在classstyle属性,那么新添加的值会被自动合并,而不是覆盖。

禁用属性传承

不希望根元素继承属性,可以添加inheritAttrs:false

Vue.component('base-input', {
 inheritAttrsfalse,
 props: ['label''value'],
 template: `
   <label>
     {{ label }}
     <input
       v-bind="$attrs"  
       v-bind:value="value"
       v-on:input="$emit('input', $event.target.value)"
     >
   </label>
 `
})

上述例子中,若没有v-bind =$attrs 则传递的非prop属性会自动添加到label 标签。

边界情况

该节主要对Vue 中涉及到的一些小细节和规则进行说明。

访问元素/组件

Vue中,我们一般不手动操作DOM元素,也不会干涉一个组件实例的内部,但是如果一定要这么做,也是可以的,接下来对几种可能的情况进行讨论:

访问根实例

new Vue 实例的子组件中,要访问根实例,可以通过$root 属性进行访问,例如:

new Vue({
 data: {
   foo1
},
 computed: {
   bar: function () { /* ... */ }
},
 methods: {
   baz: function () { /* ... */ }
}
})
​
//使用方法
this.$root.foo  //获取
this.$root.foo = 2 //写入
this.$root.bar //访问计算属性
this.$root.baz()  //调用根组件方法
访问父级组件实例

$parent属性 ,用法与根组件一样。

用这种方式也可以替代使用prop父传子的数据传输方式。

访问子组件实例

使用ref 与子组件建联。

<base-input ref="usernameInput"></base-input>

定义了ref 之后,在base-input组件内,可以使用this.$ref.usernameInput 来访问该组件实例。

依赖注入

如果有多个组件存在嵌套,那么直接使用$parent 会不易维护,这种情况下推荐使用依赖注入,涉及到provideinject

provide:允许我们指定想给后代组件提供的数据/方法。

provide:function(){
 return {
   getMapthis.getMap //将父组件中的getMap传出去
}
}

设定完后,可以在任何后代组件使用inject来接收。

inject: ['getMap']  //后代组件接收父组件中传来的getMap
//可以使用this.getMap来调用。

程序化事件监听

  • 监听一个事件: $on(事件名,事件处理函数)
  • 一次性监听一个事件:$once(事件名,事件处理函数)
  • 停止监听一个事件:$off(事件名,事件处理函数)
mounted: function () {
 var picker = new Pikaday({
   field: this.$refs.input,
   format'YYYY-MM-DD'
})
​
 this.$once('hook:beforeDestroy'function () {
   picker.destroy()
})
}

循环引用

循环引用的组件个人认为使用较少,也没有特别大的实用价值,因此暂时不作记录,日后再更。

控制更新

可以在根元素上使用v-once来创建低开销的静态组件。若一个组件内含有大量静态元素,那么可以使用这种方法,使得加载完成后被缓存起来,下次就不用再被加载了。可以提高速度。

Vue.component('my-component', {
 template: `
   <div v-once>
     <h1>Terms of Service</h1>
     ... a lot of static content ...
   </div>
 `
})