vue-cli
什么是 vue- cli
tip vue-cli 是 Vue.js 开发的标准工具。它简化了程序员基于 webpack 创建工程化的 Vue 项目的过程。
安装与使用
安装
npm -g @vue/cli |
使用 快速初始化
vue create 项目名字 |
运行流程
vue 通过 main.js 把 app.vue 渲染到 index.html 指定区域
- app.vue 用来编写待渲染的模板结构
- index.html 中需要预留 el 区域
vue 组件的三个组成部分
template(组件的模板结构)
<template> |
- 每个组件的模板结构 ,需要调用到 template
- template 的 vue 提供的容器标签 ,只有包裹性作用,不会渲染为真正的DOM元素
- template 只能包含唯一的根节点
- 简单理解里面写 HTML即可
script(组件的 JavaScript 行为)
<script> |
style (组件的样式)
<style> |
添加less 语法支持
<style leng="less"> |
每个组件中必须包含 template 模板结构,而 script 行为和 style 样式是可选的组成部分
组件关系
封装好 App.vue Left.vue Right.vue 之后,彼此间相互独立不存在关系
使用组件
<template> |
全局组件
通过 components 注册的是私有子组件
在组件 A 的 components 节点下,注册了组件 F。
则组件 F 只能用在组件 A 中;不能被用在组件C 中。
注册全局组件
在 vue 项目的 main.js
入口文件,通过 Vue.component()
注册全局组件
// 导入需要注册的全局组件 |
props (自定义属性)
tip props 是组件的自定义属性,在封装通用组件的时候,合理地使用props 可以极大的提高组件的复用性!
导入组件后以标签形式使用组件 在标签即可使用 自定义属性
<!-- 绑定自定义属性 --> |
// count.vue |
tip
vue 规定:组件中封装的自定义属性是只读的,程序员不能直接修改 props 的值
要想修改 props 的值,可以把 props 的值转存到 data 中,因为 data 中的数据都是可读可写的!
组件冲突问题
默认情况下,写在 .vue 组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。
导致组件之间样式冲突的根本原因是:
- 单页面应用程序中,所有组件的 DOM 结构,都是基于唯一的 index.html 页面进行呈现的
- 每个组件中的样式,都会影响整个 index.html 页面中的 DOM 元素
style 节点的 scoped 属性
为了提高开发效率和开发体验,vue 为 style 节点提供了 scoped 属性,从而防止组件之间的样式冲突问题
<style leng="less" scoped > |
- 原理:为当前组件所有 DOM 元素分配唯一的自定义属性,写样式时使用属性选择器防止样式冲突问题
scoped
只给子组件最外层的 div 添加了自定义属性[data-v-xxx]
,子组件内部的标签并没有添加。因此父组件只能修改子组件最外层的 div 样式,修改子组件内层元素的样式是不可行的- 若想让某些样式对子组件生效,需使用
/deep/
深度选择器 (常用于修改 第三方 ui 组件库 )
/* 细细品味 */ |
组件数据共享
父子间的共享
父向子共享
父组件向子组件共享数据需要使用自定义属性 (props)
父组件
<son :msg="message" :user="userinfo"></son> |
子组件
<p>父组件传递过来的 msg 是 :{{msg}}</p> |
子向父共享
子组件向父组件共享数据使用自定义事件。
子组件
export default{ |
父组件
<son @numChange="getCount"></son> |
兄弟间共享
在 vue2.x 中,兄弟组件之间数据共享的方案是EventBus。
EventBus 的使用步骤:
- 创建
eventBus.js
模块,并向外共享一个Vue 的实例对象
- 在数据发送方,调用
bus.$emit('事件名称', 要发送的数据)
方法触发自定义事件 - 在数据接收方,调用
bus.$on('事件名称', 事件处理函数)
方法注册一个自定义事件
兄弟组件 A(数据发送方)
<!--定义一个按钮 触发 --> |
eventBus.js
import Vue from 'vue' |
兄弟组件 C(数据接收方)
<p>兄弟组件 A 共享的数据 :{{ msgFromLeft }}</p> |
生命周期
概念:每个组件从创建 -> 运行 -> 销毁的一个过程,强调的是一个时间段!
tip 生命周期阶段
tip 官方生命周期图示
ref 引用
每个 vue 的组件实例上,都包含一个$refs
对象,里面存储着对应的DOM 元素或组件的引用。默认情况下,组件的 $refs
指向一个空对象。
引用 dom 元素
<!-- 使用 ref 属性,为对应的 dom 元素添加引用的名称 --> |
引用组件实例
<!-- 使用 ref 属性,为对应的组件添加引用的名称 --> |
this.$nextTick(cb) 方法
组件的 $nextTick(cb)
方法,会把 cb 回调推迟到下一个 DOM 更新周期之后执行,即在 DOM 更新完成后再执行回调,从而保证 cb 回调可以获取最新的 DOM 元素
methods: { |
动态插件
vue
提供了一个内置的<component>
组件,专门用来实现动态组件的渲染
<script> |
keep-alive
在默认情况下,切换组件会将不需要的组件销毁,导致组件的数据清空,切换回来时数据不能还原到切换前
为了保持组件的状态可以使用 vue 内置的 <keep-alive>
组件
<keep-alive> |
使用 <keep-alive>
组件后,动态切换组件时不需要的组件就会被缓存,切换回来时重新被激活
keep-alive 对应的生命周期函数
- 组件被激活时,触发组件的
deactived
生命周期函数 - 组件被销毁时,触发组件的
activated
生命周期函数
export default { |
keep-alive 的 include
属性
include
属性用来指定,只有匹配名称的组件才会被缓存,其他销毁
<keep-alive include="Left"> |
keep-alive 的 exclude
属性
功能与 include
相反,排除不缓存的组件
如果同时使用 include, exclude, 那么 exclude 优先于 include
include 和 exclude 避免混乱只用一个就好
插槽
插槽(slot)是封装组件时,把不确定的,希望由用户指定部分定义为插槽
简单来讲,组件封装期间,为用户预留的内容的占位符。
基础用法
封装组件时,用 <slot>
元素定义插槽,预留占位符
<!-- my-com.vue --> |
使用
<my-com> |
如果在封装组件时没有预留 slot
任何插槽,用户自定义的内容不生效,会被丢弃
后备内容
在封装组件时,可以为预留的 <slot>
插槽的提供后备内容(默认内容)
<slot> |
如果组件使用者没有为插槽提供任何的内容,后备内容就会生效
用户提供内容后,后备内容就会被覆盖掉
具名插槽
如果在封装组件时需要预留多个插槽节点,则需要为每个 <slot>
插槽指定具体的 name 名称。这种带有具体名称的插槽叫做“具名插槽”。
<!-- my-com.vue --> |
为具名插槽提供内容,在一个 <template>
元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称
<my-com> |
注意:没有指定 name 名称的插槽,会有隐含的名称叫做 “default”。
具名插槽的简写形式: (v-slot:)
替换为字符 #
,例如 v-slot:header
可以被简写为 #header
作用域插槽
在封装组件过程中,为预留的 solt 插槽绑定 props 数据,叫做作用域插槽
数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定
<template> |
可以使用 v-slot: 的形式,接收作用域插槽对外提供的数据
<my-com> |
接收到的数据 scope
是一个对象。
// scope 的内容 |
在接收作用域插槽提供的数据时可以使用解构赋值。
<my-com> |
自定义指令
私有自定义指令
在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令
directives: { |
使用:需要加上 v- 前缀
<!-- 上面声明的自定义指令名为 color --> |
动态绑值
data:{ |
<h1 v-color="color">app组件</h1> |
通过 binding 获取指令的参数值
directives: { |
update 函数
bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时 bind 函数不会被触发。 update 函数会在每次 DOM 更新时被调用
directives: { |
简写
insert 和update 函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式
directives: { |
全局自定义指令
全局共享的自定义指令需要通过 Vue.directive()
进行声明
// 全局写法 |
注意事项
- 自定义指令使用时需要添加
v-
前缀 - 指令名如果是多个单词,要使用
camel-case
短横线命名方式,不要用camelCase
驼峰命名 - 自定义指令三个函数里的
this
指向window
<span v-big-number="n"></span> |
data() { |