昔洛 的个人博客

Bug不空,誓不成佛

  menu
70 文章
14633 浏览
2 当前访客
ღゝ◡╹)ノ❤️

Vue 框架学习(四)

学习内容

  • ESLint
  • elementUI 组件库
  • 插槽
    • 命名插槽
    • 作用域插槽
  • watch 监听器
  • 深度作用选择器
  • 大数字处理 json-bigint
    • axios 原生数据转换器
  • 父子组件相互传值

ESLint

ESLint最初是由Nicholas C. Zakas 于2013年6月创建的开源项目,目标是提供一个插件化的 JavaScript 代码规范检测工具

  • 目标:全部开发人员都使用同一种风格的 JavaScript 代码开发项目
  • 好处:提升项目开发速度、增强代码可维护性
  • 应用
  • 步骤:
    • 开启 eslint 规范检测,具体在 vue.config.js 中配置如下:
      lintOnSave: true, // 文件保存时,就做 eslint 规范检测
    • 具体规范
      • 声明变量但是未使用会报错
      • 简单语句结尾不能有分号
      • 给变量复制等号左右要求有空格
      • 在行结尾处,多余的空格不允许
      • 字符串必须使用单引号圈选,不能是双引号
      • 对象 成员名称冒号 与 值 之间需要有一个空格
      • 方法名称小括号 的左右需要保留一个空格
      • 在每一个文件的结尾处,必须有一个空行
      • 文件中如果出现空白行,要求只能有一行空白,不能连续出现两行或以上的空白行
      • 。。。
  • 注意:
    • 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 方式安装
  • 打开 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);
      
  • 按需引入使用
    • 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
  • 注意:
    • 运行指令 npm run build(是打包指令) 在输出信息中可以比较看出按需引入完整引入打包文件大小差别,按需引入的打包文件大小较小则后期项目上线性能会更好
    • 按需引入根据内容可以分为:css样式、组件、事件方法 3种
    • 为了方便开发,前期只做css样式按需引入,待项目开发完毕后,再给组件事件方法 做统计按需引入
    • 如果按需引入配置完毕,发现页面按钮没有css效果,请重启服务npm run serve

插槽

根据业务需要,父组件可以给子组件传值,但一般传递的都是比较少量的信息(例如单个的String/Number/Boolean/Object/Array等),如果要传递的数据非常多,例如一大段html标签内容,则不合适,这时可以通过 插槽 实现

  • 父子组件嵌套情形,子组件给自己个性化区域设置一个占位符,父组件给占位符填充内容,占位符就是 插槽
    598.png

简单应用(匿名插槽)

  • 匿名插槽定义语法:
    <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自己传递,父组件关注外在表现,子组件插槽关注核心数据,子组件给插槽定义要使用的数据,这个数据只是自己应用区域可见 故称为 作用域插槽

599.png

  • 语法
    • 插槽给自己生命数据
      <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(名称,数据,数据……) 是组件调用自己方法的固定方式,第一个参数是被调用方法的名称,后续参数都是给方法传递的实参信息

内事不懂问百度,外事不懂问谷歌~