学习内容
- ESLint
- elementUI 组件库
- 插槽
- 命名插槽
- 作用域插槽
- watch 监听器
- 深度作用选择器
- 大数字处理 json-bigint
- axios 原生数据转换器
- 父子组件相互传值
ESLint
ESLint最初是由Nicholas C. Zakas 于2013年6月创建的开源项目,目标是提供一个插件化的 JavaScript 代码规范检测工具
- 目标:全部开发人员都使用同一种风格的 JavaScript 代码开发项目
- 好处:提升项目开发速度、增强代码可维护性
- 应用
- 步骤:
- 开启 eslint 规范检测,具体在 vue.config.js 中配置如下:
lintOnSave: true, // 文件保存时,就做 eslint 规范检测
- 具体规范
- 声明变量但是未使用会报错
- 简单语句结尾不能有分号
- 给变量复制等号左右要求有空格
- 在行结尾处,多余的空格不允许
- 字符串必须使用单引号圈选,不能是双引号
- 对象 成员名称冒号 与 值 之间需要有一个空格
- 方法名称小括号 的左右需要保留一个空格
- 在每一个文件的结尾处,必须有一个空行
- 文件中如果出现空白行,要求只能有一行空白,不能连续出现两行或以上的空白行
- 。。。
- 开启 eslint 规范检测,具体在 vue.config.js 中配置如下:
- 注意:
- eslint只是代码规范,不是语法错误,不规范的代码可以正常运行
- eslint只是针对 js文件 和 vue文件的js部分 做规范检查
自定义配置规则
根据自己的想法给eslint配置规范,修改配置文件.eslintrc.js,给其中的rules段做配置即可
// 匹配规则:[开启规则参数,要求/禁用参数]
'semi':['error','always'], // 简单语句后边要求设置分号,不设置会报错
'semi':['error','never'], // 简单语句后边不要设置分号,设置会报错
'semi':['off','always'], // 关闭规则检测
'semi':['off','never'], // 关闭规则检测
'space-before-function-paren': ['error', 'never'], // 禁止在function小括号左边设置空格,否则报错
'space-before-function-paren': ['error', 'always'], // 要求在function小括号左边设置空格,否则报错
'space-before-function-paren': ['off', 'always'], // 关闭规则
'space-before-function-paren': ['off', 'never'], // 关闭规则
'no-multiple-empty-lines': ['error', { 'max': 3 }], // 文件中间允许出现3个或以内的空白行
'no-multiple-empty-lines': ['off', { 'max': 3 }], // 关闭规则
开启规则参数:
error:将规则视为一个错误
off:关闭规则
要求/禁用参数:
always:要求规则
never:禁止规则
- 注意:在 .eslintrc.js 文件中对规则进行修改需要重启服务(npm run serve)才会生效
代码自动规范
- vscode插件:ESLint
- 全局方式安装eslint依赖包
- npm install -g eslint
该依赖包安装完毕是对1步骤扩展做支持的,需要通过 npm 方式安装
- npm install -g eslint
- 打开 vscode 配置文件 settings.json(by File -> Preferences->Settings)
最末尾如下内容:"eslint.enable": true, "eslint.autoFixOnSave": true, "eslint.run": "onType", "eslint.options": { "extensions": [".js",".vue"] }, "eslint.validate": [ { "language": "html", "autoFix": true }, { "language": "javascript", "autoFix": true }, { "language": "vue", "autoFix": true } ]
ElementUI 组件库
Element-UI 是 饿了么 前端团队,开源出来的一套 Vue 组件库(针对pc电脑浏览器端),内部集成了许多项目中可以使用的成熟
组件component
,既增强了用户体验、又加快的开发速度。
安装与简单使用
- yarn add element-ui
- 在 main.js 文件中引入 elementui 模块和注册
// eslint要求import系列代码都要在普通代码上边设置 // 引入elementui组件库 import ElementUI from 'element-ui' // 引入css样式 import 'element-ui/lib/theme-chalk/index.css' // 把组件库注册给Vue // 之前组件注册:Vue.component(名称,组件) 每次只能注册一个 // 现在组件注册: Vue.use(组件模块) 一次性注册"全部"的组件,非常高效 Vue.use(ElementUI)
- 在App.vue组件中简单使用elementui组件
引入使用的两种方式
- 完整引入使用
- 在项目入口文件main.js中一次性把ElementUI组件库全部的组件和方法做引入部署
import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI);
- 在项目入口文件main.js中一次性把ElementUI组件库全部的组件和方法做引入部署
- 按需引入使用
- Element-UI本身有非常多的
组件
、css样式
、方法
,在一个项目中有可能不会用到全部,如果全部引入,不用的元素会造成额外资源开销,进而影响项目性能。采取的措施就是用多少就引多少,即按需引入。elementui组件库给我们有提供3种内容:css样式、组件、事件方法 - 步骤
- yarn add babel-plugin-component -D
- 在babel.config.js文件中做如下配置
module.exports = { plugins: [ [ 'component', { 'libraryName': 'element-ui', 'styleLibraryName': 'theme-chalk' } ] ] }
- 以上两个步骤完成后,css样式 已经可以实现按需引入了(main.js中关于elementui的css样式引入已经不起作用了,鉴于代码美观可以删除 或 屏蔽 // import 'element-ui/lib/theme-chalk/index.css')
- 在main.js文件中给 组件 和 事件方法 做按需引入
// 2) 按需引入 import { Row, Button, MessageBox, Message } from 'element-ui' // 按需注册组件 Vue.use(Row) Vue.use(Button) // 按需注册事件方法(原型继承) Vue.prototype.$confirm = MessageBox.confirm Vue.prototype.$message = Message
- 可以借鉴按需导入的全部组件和事件方法: https://element.eleme.cn/#/zh-CN/component/quickstart
- Element-UI本身有非常多的
- 注意:
- 运行指令 npm run build(是打包指令) 在输出信息中可以比较看出按需引入和完整引入打包文件大小差别,按需引入的打包文件大小较小则后期项目上线性能会更好
- 按需引入根据内容可以分为:css样式、组件、事件方法 3种
- 为了方便开发,前期只做css样式按需引入,待项目开发完毕后,再给组件和事件方法 做统计按需引入
- 如果按需引入配置完毕,发现页面按钮没有css效果,请重启服务npm run serve
插槽
根据业务需要,父组件可以给子组件传值,但一般传递的都是比较少量的信息(例如单个的String/Number/Boolean/Object/Array等),如果要传递的数据非常多,例如一大段html标签内容,则不合适,这时可以通过 插槽 实现
- 父子组件嵌套情形,子组件给自己个性化区域设置一个占位符,父组件给占位符填充内容,占位符就是 插槽
简单应用(匿名插槽)
-
匿名插槽定义语法:
<slot></slot>
在一个子组件中,允许出现多个匿名插槽,它们都会接收相同内容,但一般没有实际意义
-
给插槽传递数据:
<子组件标签> 被填充到插槽的内容 </子组件标签>
-
注意:
- vue文件编译运行后slot标签会被父组件传递的信息覆盖掉,即使没有接受到信息本身也不在浏览器体现
- 一个组件根据需要可以声明多个匿名slot,每个slot会分别独立接收到相同的内容,匿名插槽在一个组件中通常只会出现一个
- 父组件给插槽传递的信息可以是 html标签 或 字符串 或 组件 等内容,并且数量没有限制
- 子组件标签内容区域信息必须与slot联系,如果子组件内部没有slot,那么这个信息会丢失
命名插槽
子组件根据需要,内部可能有多个个性化区域,这样就需要定义多个slot,为了加以区分,可以给slot定义名字,即 命名插槽
- 命名插槽语法:
<slot name="s1"></slot> <slot name="s2"></slot> <slot name="s3"></slot>
通过 name 属性给插槽定义名字
- 父组件根据名字给插槽填充内容
<子组件>
<div slot="s1">填充给name="s1"的插槽中</div>
<div slot="s2">填充给name="s2"的插槽中</div>
<p>填充给匿名插槽</p>
<div slot="s3">填充给name="s3"的插槽中</div>
<p>填充给匿名插槽</p>
<子组件>
作用域插槽
插槽应用中,父组件给插槽填充的内容通常有两部分:html标签、数据部分
实际情况是:父组件只传递html标签,数据信息要通过slot自己传递,父组件关注外在表现,子组件插槽关注核心数据,子组件给插槽定义要使用的数据,这个数据只是自己应用区域可见 故称为 作用域插槽
- 语法
- 插槽给自己生命数据
<slot xx=xx yy=yy zz=zz></slot>
通过"属性值"方式定义数据
- 父组件应用插槽数据
<子组件> <html标签 slot-scope="名称"> {{ 名称.xx }} {{ 名称.yy }} {{ 名称.zz }} </html标签> </子组件>
- 插槽给自己生命数据
- 插槽数据声明注意:
- 通过 属性值 方式声明数据,数量不限制,名称不能是name(其为命名插槽固定属性)
- 匿名、命名插槽 都可以声明数据,实现 作用域插槽 效果
- 插槽数据来源可以是 直接声明 的,也可以进行 属性绑定 获取本身组件实例的信息
- 声明数据的类型不限制(例如String、Number、Boolean、Object、Array 都可以)
- 插槽数据使用注意:
- 在html标签中声明属性值 slot-scope=名称 接收插槽声明的数据,名称是一个对象,成员就是插槽的属性名
- 接收的信息如果是数组,可以通过v-for遍历
- slot-scope 与 v-for 不能出现在同一个html标签中,确有需要,可以让它们出现在父子标签里边
watch 监听器
监听器就是一种机制,可以检测 vue 中 data 数据的变化,然后做相关处理
- 实例代码如下:
data(){ return { name:'', addr:'', cat:{ leg:'', tail:'', son:{ name:'小黄', weight:50 } } } } watch:{ data成员名称:函数(新值,旧值){} name:function(newv,oldv){}, addr:function(newv,oldv){}, 'cat.leg':function(newv,oldv){}, // 对象成员监听 'cat.tail':function(newv,oldv){}, cat: { // 深度监听,内部任意成员变化都会感知到 handler: function (newv, oldv) { /* ... */ }, deep: true }, }
- 说明:
- 监听器既可以监听普通成员、也可以监听对象成员,还可以深度监听
- 一般this可以调用的成员属性都可以监听,例如computed计算属性,但是data作为主要使用对象
- 深度监听,使用handler+deep关键字达成
深度作用选择器
当前组件A 引入一个其他组件B做应用,A组件由于scoped作用,本身的全部html标签都会包含一个 data-v-xxx 的属性名称,使得css样式达到私有效果,被使用的组件B由于某些原因,编译解析后各个html标签不会形成 data-v-xxx 的属性,这样在组件A中给组件B设置样式会导致无效,此时可以使用深度作用选择器 /deep/ 给 B 组件的某些标签设置样式
.a /deep/ .b { /* ... */ }
a是组件A的选择器,b是组件B的选择器,它们会形成如下效果
.a[data-v-f3f3eg9] .b { /* ... */ }
- 深度作用选择器: https://vue-loader.vuejs.org/zh/guide/scoped-css.html#
- 注意:
- 某些情况下>>>符号有可能无法正确解析,可以替换为别名 /deep/ 或 ::v-deep
- 深度作用选择器的左边必须是当前组件的css选择器,右边是子组件标签选择器
json-bigint
项目中如果使用一些超出javascript语言限制的大整型数字信息,该数字会变形为其他信息,为了避免产生问题,可以通过json-bigint做转换,使得大整型数字可以正常使用,这就是json-bigint的作用
- 原理:json-bigint会把大整型的数字信息拆分个小段信息存储到数组的各个元素中,待使用的时候再拼接到一起变为字符串
- 网站:https://github.com/sidorares/json-bigint
- 使用示例:
var JSONBig = require('json-bigint'); // 需要先安装 yarn add json-bigint var str = '{ "value" : 9223372036854775807, "v2": 123 }'; var obj = JSONBig.parse(str) // 字符串--->对象 console.log(obj.value) // 9223372036854775807(正确) var obj2 = JSON.parse(str) // 字符串--->对象 console.log(obj2.value) // 9223372036854776000(错误)
- 结论:json-bigint需要对一个包含大整型信息的“字符串”做转换处理变为对象,这个对象可以获得正确的大数字信息
axios 原生数据转换器
通过 axios 发起的请求,服务器给客户端返回数据的第一手处理者是 “转换器( transformResponse )”,转换器处理完毕再交给响应拦截器使用,故要对大数字信息做处理,下手点是"转换器"(响应拦截器获得数据已经是变形后的内容了)
本质上:服务器返回信息的类型是“字符串”,要经过转换器做JSON.parse()转化处理,所以响应拦截器接收到的是对象
- 示例代码如下
// 引入json-bigint
import JSONbig from 'json-bigint'
……
// 对服务器端返回来的数据信息做处理(尤其是大数字的处理)
// axios配置"数据转换器"
axios.defaults.transformResponse = [function (data) {
// 服务器端返回给客户端的data数据主要就两种类型
// 1) 字符串对象 '{xx:xx...}'
// 2) 空字符串 ''
// 在此处要利用JSONbig对返回的信息加以处理,如果不处理,系统默认是通过JSON.parse()给处理的
// 这样大数字就错误了
if (data) {
return JSONbig.parse(data)
} else {
return data
}
}]
- 注意:上述数据转换一定要设置else,以便对空字符串的做处理,因为服务器有时候会返回空字符串信息
父子组件相互传值
父传子
- 父组件要在子组件标签上通过属性值方式传值
<子组件标签 name=value name=value name=value></子组件标签>
- 子组件接收并应用值,具体通过props接收
<!--在模板中应用传递来的数据-->
<input :style="{color:xx}">
<script>
export default {
// 通过props接收父传递过来的数据,注意各个名称需要使用单引号圈选
// 具体有两种方式:
props:['xx','xx','xx'],
props:{
xx:{
type:类型限制
default:默认值
}
}
}
</script>
子传父
- 步骤:
- 父组件 向子组件 传递一个事件,本身声明事件的methods方法
- 子组件 调用 父组件 传递过来的事件,并传递相关的数据
- 父组件 通过事件方法参数获得子组件传递过来的数据并使用
- 父组件操作语法:父组件通过**@符号**向子组件传递一个事件方法
<子组件 @func1="show"></子组件> ... methods:{ show(arg1,arg2){xxxx} }
- func1为事件的名称,给子组件触发使用
- show为该事件的执行函数,在父组件内部的methods中定义好
- 在事件中可以通过形参(arg1、arg2)接收子组件出来过来的数据 并做近一步处理
- 子组件操作:子组件中,使用this.$emit()调用 父组件中的方法
$emit:使得子组件调用 自己的事件方法(父组件给声明的) this.$emit('func1', 数据, 数据) this:当前子组件对象(组件实例) func1:是父组件给子组件声明的事件方法,通过第2、3位置设置给父组件传递的数据
从第二个位置开始传递实参数据,其可以被父组件methods方法的形参所接受
$emit(名称,数据,数据……) 是组件调用自己方法的固定方式,第一个参数是被调用方法的名称,后续参数都是给方法传递的实参信息