1.Vue开发的两种方式
(1)核心包传统开发模式
基于html/css/js文件,直接引入,开发Vue。
(2)工程化开发模式(更常用的一种):
主要是基于构建工具(例如,webpack)的环境中开发Vue,可以利用构建工具编写一些高级的语法。
但是问题是需要一些复杂的配置(配置并不简单;各个项目雷同的配置;缺乏统一标准)
=> 需要一个工具,生成标准的配置!
Vue Cli 的提出!
2.Vue CLI
(1)基本介绍:
是官方提供的一个全局命令工具。
可以帮助我们 快速创建一个开发Vue 项目的标准化基础架子。(集成了 =webpack配置,即一个目录)
(2)好处:
<1>开箱即用,零配置;<2>内置babel等工具;<3>标准化;
(3)创建步骤:
<1>全局安装(一次):
yarn global add @vue/cli 或 npm i @vue/cli -g
<2>查看vue安装的版本
vue --version
<3>创建项目架子
vue create project-name (项目名-不能用中文)
(4)启动项目
进入目录,输入:
yarn serve 或者 npm run serve (serve这个名字不是固定的,可以找package.json中设置)
3.项目的目录介绍和运行流程
4.组件化开发和根组件
(1)组件化
一个页面可以拆分为一个个组件,每个组件有着自己独立的结构、样式、行为。
好处:便于维护,利于复用,能够提升开发效率。
组件分类:普通组件、根组件
(2)根组件
整个应用最上层的组件,包裹所有普通的小组件。
(3)组件的构成
每一个组件由三部分构成:
<1>template:结构,有且只能有一个根元素;
<2>script:js逻辑;
data是一个函数,一个组件的data选项必须是一个函数来保证每个组件的实例维护独立的一份数据对象。每次创建新的组件实例,都会新执行一次data函数,得到一个新的对象。
<3>style:样式(可支持 less,需要装包)
让组件支持less
<1>style标签,lang="less",开启less功能;
<2>装包: yarn add less less-loader
使用scoped:解决全局样式的问题
默认情况下:写在组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题;
(1)全局样式:默认组件中的样式会作用到全局;
(2)局部样式:可以给组件加上scoped属性,可以让样式只作用于当前的组件;
原理:使得当前组件内的标签都被添加上哈希值,最终使得当前组件的元素才会有自定义的属性;
(4)组件的注册
使用组件的注册,使得整个Vue文件相对简单和条理;
<1>普通组件的注册-局部注册
<2>普通组件的注册-全局注册
注册的时候,组件名和组件对象是一样的,可省略组件对象
5.组件之间的通信
组件通信,就是指组件与组件之间的数据传递。由于组件之间的数据是独立的,无法直接访问其他组件的数据,当我们想用其他组件的数据,那此时就涉及到了组件通信;
首先要考虑组件之间的关系有两种,
<1>父子关系
// 简单的一种
props: {
校验的属性名: 类型 // Number String Boolean ...
},
// 自定义校验
props: {
校验的属性名: {
type: 类型, // Number String Boolean ...
required: true, // 是否必填
default: 默认值, // 默认值
validator (value) {
// 自定义校验逻辑
return 是否通过校验
}
}
},
最后再总结一下,data vs. props,我们知道,这两种都可以给组件传递数据;
对于 data,他是组件内部的数据,因而是可以随便改;
但是对于 props,他是外部传来的数据,不能直接改,要遵循单向数据流;(即我们不能直接在子组件中更改参数的值,应该使用函数并且配合$emit告诉父组件使得父组件来进行更改)
<2>非父子关系
对于父子关系的处理,event bus 事件总线,一般是一对多半的关系,因而不建议使用,更倾向于-> 全局 Vue
扩展,针对与孙子组件,爷组件无需通过父组件才能实现对孙组件的传递;
在这里要注意的是,当我们使用一下的方式进行传参的时候,要注意两种不同的写法:复杂的写法(即响应式)和简单的写法(非响应式);
<3>v-model实现组件之间的通信
原理:v-model本质上是一个语法糖,例如应用在输入框上,就是 value属性和input事件的合写;
作用:提供数据的双向绑定(1)数据变,视视图跟着变 :value (2)视图变,数据跟着变 @input
注意:$event 用在模板中,获取事件的形参
<template>
<div id="app" >
<--! 这两种的效果是一样的-->
<input v-model="msg" type="text">
<input :value="msg" @input="msg = $event.target.value" type="text">
</div>
</template>
简化其实就是利用v-model的属性和其本身的input的函数;
<4>sync组件间通信
相对于v-model属性名比较复杂,但是对于弹窗类的一般使用;
6.ref & $refs 获取dom元素和组件实例
作用:利用 ref 和 $refs 可以用于获取 dom 元素或者组件实例
特点:相对于 id or class查找范围更加精准,在当前组件内
// 基于准备好的dom,初始化echarts实例.查找范围在当前页面,很容易冲突
const myChart = echarts.init(document.querySelector('.box'));
(1)获取dom
目标标签 - 添加 ref 属性
<div ref="chartRef">我是渲染图表的容器</div>
在恰当时机(一般在 mounted中),通过 this. $refs.xxx ,来获取目标标签
mounted () {
console.log(this.$refs.chartRef)
},
(2)获取组件:
<BaseForm ref="baseForm"></BaseForm>
this.$refs.baseForm.组件方法()
(3)$nextTick
vue异步更新Dom,想要在 Dom 更新完之后做某一件事情,可以使用 $nextTick,定时器也可以实现这个效果,但是$nextTick更加精准;
this.$nextTick(() => {
// 业务逻辑
})
Notes:ref 经常在代码中得到使用,一般在mounted中配合$nextTick对其进行调用;也可以通过使用其来获得某个dom的长度和宽度,探究更多的用法;
小Tips:
1.涉及到父子通信的问题,应当考虑渲染数据的位置在哪里?如果都用得上,建议存放在父组件中;
2.其实对于组件之间的通信,一般还是使用全局vue通信较多;