vue中waiting for update signal from wds_10个vue快捷开发技巧助你成为中级前端工程师!(二)...

f9c10457b98b6e70d473d19360be34fb.png

前言

先赞再看,养成习惯~

优雅更新props


更新 prop 在业务中是很常见的需求,但在子组件中不允许直接修改 prop,因为这种做法不符合单向数据流的原则,在开发模式下还会报出警告。因此大多数人会通过 $emit 触发自定义事件,在父组件中接收该事件的传值来更新 prop


child.vue:

export defalut {props: {title: String  },methods: {changeTitle(){this.$emit('change-title', 'hello')}}
}

parent.vue:

<child :title="title" @change-title="changeTitle"></child>
export default {data(){return {title: 'title'}  },methods: {changeTitle(title){this.title = title}}
}

这种做法没有问题,我也常用这种手段来更新 prop。但如果你只是想单纯的更新 prop,没有其他的操作。那么 sync 修饰符能够让这一切都变得特别简单。

parent.vue:

<child :title.sync="title"></child>

child.vue:

export defalut {props: {title: String  },methods: {changeTitle(){this.$emit('update:title', 'hello')}}
}

只需要在绑定属性上添加 .sync,在子组件内部就可以触发 update:属性名 来更新 prop。可以看到这种手段确实简洁且优雅,这让父组件的代码中减少一个“没必要的函数”。
参考文档

在学习web前端的过程中,往往因为没有资料或者没人指导从而导致自己不想学,因此我特意准备了个qun,整理了一份最全面前端学习资料,从最基础的HTML+CSS+JS 到移动端HTML5的项目实战的学习资料都有整理,想学习的都可以申请加入

前端开发​jq.qq.com

送给每一位前端小伙伴, 有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入学习。


provide/inject


这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。
简单来说,一个组件将自己的属性通过 provide 暴露出去,其下面的子孙组件 inject 即可接收到暴露的属性。


App.vue:

export default {provide() {return {app: this}} 
}

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。
简单来说,一个组件将自己的属性通过 provide 暴露出去,其下面的子孙组件 inject 即可接收到暴露的属性。


App.vue:

export default {provide() {return {app: this}} 
}

在 2.5.0+ 版本可以通过设置默认值使其变成可选项:

export default {inject: {app: {default: () => ({})}},created() {console.log(this.app) }
}

如果你想为inject的属性变更名称,可以使用from来表示其来源:.

export default {inject: {myApp: {// from的值和provide的属性名保持一致from: 'app',default: () => ({})}},created() {console.log(this.myApp) }
}

需要注意的是 provideinject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。但是某些时候,或许它能帮助到我们。
参考文档


小型状态管理器


大型项目中的数据状态会比较复杂,一般都会使用 vuex 来管理。但在一些小型项目或状态简单的项目中,为了管理几个状态而引入一个库,显得有些笨重。


在 2.6.0+ 版本中,新增的 Vue.observable 可以帮助我们解决这个尴尬的问题,它能让一个对象变成响应式数据:

// store.js
import Vue from 'vue'export const state = Vue.observable({ count: 0 
})

使用:

<div @click="setCount">{{ count }}</div>
import {state} from '../store.js'export default {computed: {count() {return state.count}},methods: {setCount() {state.count++}}
}

当然你也可以自定义mutation来复用更改状态的方法:

import Vue from 'vue'export const state = Vue.observable({ count: 0 
})export const mutations = {SET_COUNT(payload) {if (payload > 0) {state.count = payload} }
}

使用:

import {state, mutations} from '../store.js'export default {computed: {count() {return state.count}},methods: {setCount() {mutations.SET_COUNT(100)}}
}

参考文档

卸载watch观察

通常定义数据观察,会使用选项的方式在 watch 中配置:

export default {data() {return {count: 1      }},watch: {count(newVal) {console.log('count 新值:'+newVal)}}
}

除此之外,数据观察还有另一种函数式定义的方式:

export default {data() {return {count: 1      }},created() {this.$watch('count', function(){console.log('count 新值:'+newVal)})}
}

它和前者的作用一样,但这种方式使定义数据观察更灵活,而且$watch会返回一个取消观察函数,用来停止触发回调:

let unwatchFn = this.$watch('count', function(){console.log('count 新值:'+newVal)
})
this.count = 2 // log: count 新值:2
unwatchFn()
this.count = 3 // 什么都没有发生...

$watch第三个参数接收一个配置选项:

this.$watch('count', function(){console.log('count 新值:'+newVal)
}, {immediate: true // 立即执行watch
})

参考文档

巧用template

相信 v-if 在开发中是用得最多的指令,那么你一定遇到过这样的场景,多个元素需要切换,而且切换条件都一样,一般都会使用一个元素包裹起来,在这个元素上做切换。

<div v-if="status==='ok'"><h1>Title</h1><p>Paragraph 1</p><p>Paragraph 2</p>
</div>

如果像上面的 div 只是为了切换条件而存在,还导致元素层级嵌套多一层,那么它没有“存在的意义”。


我们都知道在声明页面模板时,所有元素需要放在 <template> 元素内。除此之外,它还能在模板内使用,<template> 元素作为不可见的包裹元素,只是在运行时做处理,最终的渲染结果并不包含它。

<template><div><template v-if="status==='ok'"><h1>Title</h1><p>Paragraph 1</p><p>Paragraph 2</p></template></div>
</template>

同样的,我们也可以在<template>上使用v-for指令,这种方式还能解决v-forv-if同时使用报出的警告问题。

<template v-for="item in 10"><div v-if="item % 2 == 0" :key="item">{{item}}</div>
</template>

template使用v-if, template使用v-for

过滤器复用

过滤器被用于一些常见的文本格式化,被添加在表达式的尾部,由“管道”符号指示。

<div>{{ text | capitalize }}</div>
export default {data() {return {text: 'hello'}  },filters: {capitalize: function (value) {if (!value) return ''value = value.toString()return value.charAt(0).toUpperCase() + value.slice(1)}}
}

试想一个场景,不仅模板内用到这个函数,在 method 里也需要同样功能的函数。但过滤器无法通过 this 直接引用,难道要在 methods 再定义一个同样的函数吗?
要知道,选项配置都会被存储在实例的 $options 中,所以只需要获取 this.$options.filters 就可以拿到实例中的过滤器。

export default {methods: {getDetail() {this.$api.getDetail({id: this.id}).then(res => {let capitalize = this.$options.filters.capitalizethis.title = capitalize(res.data.title)})}}
}

除了能获取到实例的过滤器外,还能获取到全局的过滤器,因为 this.$options.filters 会顺着 __proto__ 向上查找,全局过滤器就存在原型中。
自定义指令获取实例
有的情况下,当需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。像是项目中常用的权限指令,它能精确到某个模块节点。大概思路为获取权限列表,如果当前绑定权限不在列表中,则删除该节点元素。

Vue.directive('role', {inserted: function (el, binding, vnode) {let role = binding.valueif(role){const applist = sessionStorage.getItem("applist")const hasPermission = role.some(item => applist.includes(item)) // 是否拥有权限if(!hasPermission){el.remove() //没有权限则删除模块节点}}}
})

自定义指令钩子函数共接收3个参数,包括 el (绑定指令的真实dom)、binding (指令相关信息)、vnode (节点的虚拟dom)。


假设现在业务发生变化,applist 存储在 vuex 里, 但指令内想要使用实例上的属性,或者是原型上的 $store。我们是没有办法获取到的,因为钩子函数内并没有直接提供实例访问。vnode 作为当前的虚拟dom,它里面可是绑定到实例上下文的,这时候访问 vnode.context 就可以轻松解决问题。

Vue.directive('role', {inserted: function (el, binding, vnode) {let role = binding.valueif(role){// vnode.context 为当前实例const applist = vnode.context.$store.state.applistconst hasPermission = role.some(item => applist.includes(item)) if(!hasPermission){el.remove()}}}
})

优雅注册插件


插件通常用来为 Vue 添加全局功能。像常用的 vue-routervuex 在使用时都是通过 Vue.use 来注册的。Vue.use 内部会自动寻找 install 方法进行调用,接受的第一个参数是 Vue 构造函数。

一般在使用组件库时,为了减小包体积,都是采用按需加载的方式。如果在入口文件内逐个引入组件会让 main.js 越来越庞大,基于模块化开发的思想,最好是单独封装到一个配置文件中。配合上 Vue.use,在入口文件使用能让人一目了然。


vant.config.js:

import {Toast,Button
} from 'vant'const components = {Toast,Button
}const componentsHandler = {install(Vue){Object.keys(components).forEach(key => Vue.use(components[key]))}
}export default componentsHandler

main.js:

import Vue from 'vue'
import vantCompoents from '@/config/vant.config'Vue.config.productionTip = falseVue.use(vantCompoents)new Vue({render: h => h(App)
}).$mount('#app')

参考文档


自动化引入模块


在开发中大型项目时,会将一个大功能拆分成一个个小功能,除了能便于模块的复用,也让模块条理清晰,后期项目更好维护。


像 api 文件一般按功能划分模块,在组合时可以使用 require.context 一次引入文件夹所有的模块文件,而不需要逐个模块文件去引入。每当新增模块文件时,就只需要关注逻辑的编写和模块暴露,require.context 会帮助我们自动引入。


需要注意 require.context 并不是天生的,而是由 webpack 提供。在构建时,webpack 在代码中解析它。

let importAll = require.context('./modules', false, /.js$/)class Api extends Request{constructor(){super()//importAll.keys()为模块路径数组importAll.keys().map(path =>{//兼容处理:.default获取ES6规范暴露的内容; 后者获取commonJS规范暴露的内容let api = importAll(path).default || importAll(path)Object.keys(api).forEach(key => this[key] = api[key])})}
}export default new Api()

require.context 参数:

  1. 文件夹路径
  2. 是否递归查找子文件夹下的模块
  3. 模块匹配规则,一般匹配文件后缀名

只要是需要批量引入的场景,都可以使用这种方法。包括一些公用的全局组件,只需往文件夹内新增组件即可使用,不需要再去注册。如果还没用上的小伙伴,一定要了解下,简单实用又能提高效率。
参考文档


路由懒加载(动态chunkName)


路由懒加载作为性能优化的一种手段,它能让路由组件延迟加载。通常我们还会为延迟加载的路由添加“魔法注释”(webpackChunkName)来自定义包名,在打包时,该路由组件会被单独打包出来。

let router = new Router({routes: [{path:'/login',name:'login',component: import(/* webpackChunkName: "login" */ `@/views/login.vue`)},{path:'/index',name:'index',component: import(/* webpackChunkName: "index" */ `@/views/index.vue`)},{path:'/detail',name:'detail',component: import(/* webpackChunkName: "detail" */ `@/views/detail.vue`)}]
})

上面这种写法没问题,但仔细一看它们结构都是相似的,作为一名出色的开发者,我们可以使用map循环来解决这种重复性的工作。

const routeOptions = [{path:'/login',name:'login',},{path:'/index',name:'index',},{path:'/detail',name:'detail',},
]const routes = routeOptions.map(route => {if (!route.component) {route = {...route,component: () => import(`@/views/${route.name}.vue`)}}return route
})let router = new Router({routes
})

在书写更少代码的同时,我们也把“魔法注释”给牺牲掉了。总所周知,代码中没办法编写动态注释。这个问题很尴尬,难道就没有两全其美的办法了吗?


强大的 webpack 来救场了,从 webpack 2.6.0 开始,占位符 [index] 和 [request] 被支持为递增的数字或实际解析的文件名。我们可以这样使用“魔法注释”:

const routes = routeOptions.map(route => {if (!route.component) {route = {...route,component: () => import(/* webpackChunkName: "[request]" */ `@/views/${route.name}.vue`)}}return route
})

参考文档, 参考文章

最后

往期相关文章:

我很酷:前端20个真正灵魂拷问,吃透这些你就是中级前端工程师!​zhuanlan.zhihu.com
69449842b6a22362b877cb2e0e7dd6ed.png
我很酷:10个vue快捷开发技巧助你成为中级前端工程师!​zhuanlan.zhihu.com

喜欢本文的还请点个star~有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入我的前端开发群学习。

前端开发​jq.qq.com
原文链接:https://juejin.im/post/5f179100f265da22e27a9833

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/427071.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python开发学习笔记之六(面向对象)

面向对象引入&#xff1a; 现在有一个这样的需求&#xff1a;做汽水。 在之前的学习中&#xff0c;我们怎样处理这种类似的问题呢&#xff1f;思考一下&#xff0c;哦&#xff0c;不就是分步骤做嘛&#xff0c;把复杂的问题简单化&#xff0c;分成一个一个的步骤&#xff0c;就…

wampserver php乱码,WampServer搭建php环境可能遇到的问题

WampServer搭建php环境可能遇到的问题1.安装时报错&#xff0c;缺少 MSVCR100.dll 文件这是因为wampServer安装时用到的vc库没有更新&#xff0c;要安装更新之后再进行安装&#xff0c;因为之前安装的VC版本低了&#xff0c;才导致安装的时候提示丢失MSVCR100.dll文件。以下分别…

python总结字典集合列表_python 列表,元组,字典,集合,字符串相互转换

本文主要介绍列表&#xff0c;元组&#xff0c;字典&#xff0c;集合以及和字符串之间的相互转换。1. 列表与元组的互换# 将列表转化为元组li [1, 2, 3]t tuple(li)print(t, type(t))# 打印结果:(1, 2, 3) # 将元组转换成列表tu (1, 2, 3)li list(tu)print(li, type(li))# …

hbase简介(大数据技术)

HBase是什么? HBase是建立在Hadoop文件系统之上的分布式面向列的数据库。它是一个开源项目&#xff0c;是横向扩展的。 HBase是一个数据模型&#xff0c;类似于谷歌的大表设计&#xff0c;可以提供快速随机访问海量结构化数据。它利用了Hadoop的文件系统&#xff08;HDFS&…

NAT地址转换

2017年1月12日, 星期四NAT地址转换SNAT&#xff1a;源地址转换DNAT&#xff1a;目标地址转换null转载于:https://www.cnblogs.com/jxhd1/p/9521173.html

mysql l日志分析,MySQL的截取与分析日志文件

在处理过程中&#xff0c;对几种常用的日志截取方法进行了汇总和测试&#xff1a;截取日志段的的方法汇总与测试方式一&#xff1a; 确定时间段的行号&#xff0c;使用head和tail命令截取 搜索时间&#xff1a; Time: 151212 00:00:00 先到gg&#xff0c;到文件最前面&#xff…

slide简介(大数据技术)

2.1SLIDER产生背景 为了解决MR1扩展性差、可靠性差、资源利用率低和无法支持多种计算框架等局限性&#xff0c;Apache社区将其升级了计算框架MRv2。Hadoop将资源管理功能抽象成了一个独立的通用系统YARN 在以MapReduce为核心的软件栈中&#xff0c;资源管理系统YARN是可插拔的&…

修改小程序swiper 点的样式_高质量的微信小程序样式模板应该长什么样?

现在不懂技术的小白若想快速制作自己的小程序&#xff0c;一般是通过小程序模板来实现。通过在模板上添加自己的图片、文字、商品等等&#xff0c;可以很简单地生成一个小程序。不过要想把小程序做得好看&#xff0c;你得找高质量的小程序样式模板才行。那么高质量的微信小程序…

spark简介(大数据技术)

Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的类Hadoop MapReduce的通用并行框架&#xff0c;Spark&#xff0c;拥有Hadoop MapReduce所具有的优点&#xff1b;但不同于MapReduce的是——…

python的concat用法_python的concat等多种用法详解

本文为大家分享了python的concat等多种用法&#xff0c;供大家参考&#xff0c;具体内容如下1、numpy中的concatenate()函数&#xff1a;>>> a np.array([[1, 2], [3, 4]])>>> b np.array([[5, 6]])>>> np.concatenate((a, b), axis0)array([[1, …

impala简介(大数据技术)

一、Impala概述 什么是Impala&#xff1f; Impala是用于处理存储在Hadoop集群中的大量数据的MPP&#xff08;大规模并行处理&#xff09;SQL查询引擎。 它是一个用C 和Java编写的开源软件。 与其他Hadoop的SQL引擎相比&#xff0c;它提供了高性能和低延迟。 换句话说&#xf…

论蒟蒻的作死程度

各个BT游戏进度记录 I wanna I wanna be the guy 德古拉&#xff08;为什么我没有连发器……&#xff09; 车万 东方红魔乡&#xff1a; nomal第四面 东方妖妖梦&#xff1a; 第五面 东方永夜抄&#xff1a; easyGOODENDING nomal第六面 转载于:https://www.cnblogs.com/tt66ea…

猎豹网matlab视频百度云,猎豹网校C++ Primer初级全套视频教程

1_CppPrimer_快速入门2_CppPrimer_基本内置类型3_CppPrimer_习题解答_2-34_CppPrimer_字面值常量5_CppPrimer_变量6_CppPrimer_变量名7_CppPrimer_定义对象8_CppPrimer_声明和定义9_CppPrimer_名字的作用域10_CppPrimer_const限定符11_CppPrimer_引用12_CppPrimer_typedef13_Cp…

elasticsearch简介(大数据技术)

ElasticSearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索、分析和探索的能力。充分利用ElasticSearch的水平伸缩性&#xff0c;能使数据在生产环境变得更有价值。ElasticSearch 的实现原理主要分为以下几个步骤&#xff0c;首先用户将…

python转为字节_将字节转换为python中的位

I am working with Python3.2. I need to take a hex stream as an input and parse it at bit-level. So I usedbytes.fromhex(input_str)to convert the string to actual bytes. Now how do I convert these bytes to bits?解决方案Another way to do this is by using the…

Linux 监控数据库资源占用

1.用xshell连接远程服务器&#xff0c;登录用户名和密码 2.进入远程服务器 3.输入top&#xff0c;回车&#xff0c;显示如下图所示 4.Cpu states: cpu状态 0&#xff0c;2&#xff0c;4&#xff0c;6 说明cpu是四核的 IDLE 代表闲置CPU百分比 百分号前面数字越大&#xff…

mysql操作窗口如何设置粘贴,Access6.5在表中复制和粘贴数据

在城市和省份两个字段里有很多重复的内容每次都输入一遍显得非常麻烦我们可以结合复制和粘贴数据两个命令将一个数据块很方便地放到很多位置上去 首先打开Access 的剪贴板单击视图菜单将鼠标移动到工具选项上在工具选项右边弹出一个菜单单击上面的剪贴板命在城市和省份两个字段…

windows下python安装

第一步&#xff1a;下载Python安装包 在Python的官网 www.python.org 中找到最新版本的Python安装包&#xff0c;点击进行下载&#xff0c;请注意&#xff0c;当你的电脑是32位的机器&#xff0c;请选择32位的安装包&#xff0c;如果是64位的&#xff0c;请选择64位的安装包&am…

ssdp协议_Cotopaxi:使用指定IoT网络协议对IoT设备进行安全测试

cotopaxi是用于IoT设备安全测试的工具集。你可以指定IoT网络协议(如CoAP&#xff0c;DTLS&#xff0c;HTCPCP&#xff0c;mDNS&#xff0c;MQTT&#xff0c;SSDP)进行测试。安装只需从git克隆代码即可&#xff1a;https://github.com/Samsung/cotopaxi要求目前Cotopaxi仅适用于…

ORACLE中数据类型

ORACLE中数据类型 1.在ORACLE中包含有&#xff1a;数值类型 字符串类型 日期类型等等 2.数值类型--- 1&#xff09;number 在不设置宽度的情况下&#xff0c;默认是38个最大值 如果设置宽度&#xff0c;那么方式&#xff1a;number(2)--表示宽度为2的整型数据类型 如果设置小数…