首页

JavaScript事件和修改this指向

前端达人

1、鼠标事件:

onclick 左键单击 ondblclick 左键双击 onmouseover onmouseenter 鼠标移入 onmouseout onmouseleave鼠标移出 onmousedown 鼠标按下 onmousmove 鼠标移动(鼠标滑动) onmouseup 鼠标抬起 oncontextmenu 右键单击(右键菜单)

 2、键盘事件:

onkeydown onkeypress 键按下 onkeyup 键抬起 键盘事件必须放在整个文档(document)里面去操作,不能放在节点里面去操作

3、系统事件:

onload 加载完成后 onerror 加载出错后 onresize 窗口调整大小时 onscroll 滚动时


  1. //onload 加载完成后 onerror 加载出错后 onresize 窗口调整大小时 都是放在window的身上
  2. window.onload = function(){};
  3. //onscroll 滚动时 可以放在document和window身上
  4. document.onscroll = function(){};

 4、表单事件:

onfocus 获取焦点后 onblur 失去焦点后 onchange 改变内容后 onreset 重置后 onselect 选择后 onsubmit 提交后

5、监听事件(绑定事件)写法:

节点.事件 = 函数

document.getElementById("main").onclick = function(){alert(1)};

document.getElementById("main").addEventListener("click",function(){},false);

行内绑定

<button οnclick="alert('hello world')">Click</button>

 <button οnclick="func()">Click</button>

<script type="text/javascript">

          var func = () => {

                    alert('hello world')

          };

</script>

6、事件函数this指向:在事件函数中,关键词 this 就表示触发事件的这个节点对象。

 7、修改this指向:

call() 第一个参数为 函数this将要修改指向的对象 函数有参数时 后面, 一一跟上即可 可以主动执行函数

apply() 第一个参数为 函数this将要修改指向的对象 函数有参数时 数组包一下 可以主动执行函数

bind() 第一个参数为 函数this将要修改指向的对象 函数有参数时 后面, 一一跟上即可 不不不会主动执行函数 但会return函数本体 再加一个括号即可执行  


  1. window.a = 0 //在window对象下创建一个属性,属性值为0
  2. let obj1 = {
  3. a: 1
  4. }
  5. let obj2 = {
  6. a: 2
  7. }
  8. function fn(num1, num2, num3) {
  9. console.log(this.a);
  10. console.log(num1, num2, num3);
  11. }
  12. //修改函数里面this的指向
  13. fn.call(obj1,4,5,6)
  14. fn.apply(obj2,[4,5,6])
  15. fn.bind(obj1,4,5,6)()

 


蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

Vue的双向数据绑定原理是什么?

前端达人

vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。 具体步骤: 第一步:需要

observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter,这样的 话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。 第二步:compile 解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对 应的节点绑定更新函数, 添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。 第三步:Watcher 订阅者是

Observer 和 Compile 之间通信的桥梁,主要做的事情是:

1、在自身实例化时往属 性订阅器(dep)里面添加自己

2、自身必须有一个 update()方法

3、待属性变动 dep.notice()通知时,能调用自身的update()方法,并触发 Compile 中绑定的回调,则功成身退。 第四步:MVVM 作为数据绑定的入口, 整合 Observer、Compile 和 Watcher 三者,通过 Observer 来监听自己 的 model 数据变化,通过Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信 桥梁,达到数据变化 -> 视图更新;视图交互变化(input)-> 数据 model 变更的双向绑定效果。









蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

SpringBoot与Vue交互解决跨域问题

前端达人

Hello,你好呀,我是灰小猿,一个超会写bug的程序猿!

最近在利用springboot+vue整合开发一个前后端分离的个人博客网站,所以这一篇总结一下在开发中遇到的一个问题,关于解决在使用vue和springboot在开发前后端分离的项目时,如何解决跨域问题。在这里分别分享两种方法,分别在前端vue中解决和在后台springboot中解决

浏览器同源策略

为什么会出现跨域问题? 首先一个定义一定要了解,就是浏览器的同源策略,

什么是浏览器的同源策略, 简单来说就是浏览器发送请求的协议、域名和端口要和服务器接收请求的协议、域名以及端口一致。这样才能完成交互,但是很显然这样是不可能的,尤其在对于在同一台电脑上开发前后端分离的项目的时候,一定是会使用两个端口的。那么这样就形成了跨域问题。

在这里分享一下我解决跨域问题用到的两个方法,

一、VUE前端配置代理解决跨域

(1)Vue中让浏览器请求携带cookie

先说一下我是怎么发现出现跨域问题的吧,最开始我在从前端浏览器向后台发送请求的时候是没有携带浏览器的cookie的,但是这样就导致了无法对浏览器的请求进行验证,所以在后来我用了一个方法让浏览器在每次发送请求的时候在http请求头中携带上cookie,方法如下:

在vue的main.js方法中写入如下代码:

//引入axios依赖 import axios from 'axios' //让请求携带上浏览器的cookie axios.defaults.withCredentials=true Vue.prototype.$axios = axios 
  • 1
  • 2
  • 3
  • 4
  • 5

以上表示引入axios请求,也就是ajax请求,同时开启写入凭证,只有withCredentials等于true的时候,才会携带cookie。

(2)vue中配置代理解决跨域

在vue中解决跨域问题其实也比较简单,因为我们每次浏览器发送的请求中,URL的前半部分一定是相同的,比如http://localhost:8080/blogs与http://localhost:8080/login,我们就可以将他们相同的URL提取出来,封装到axios.defaults.baseURL中,这样我们在每次请求的时候,就可以将请求地址简写成“/blogs”这样,也相当于是将URL头部进行了一个简单的封装。

注意:设置统一请求路径的axios.defaults.baseURL =
"http://localhost:8080"应该写在axios.js中

但是在解决跨域问题的时候,我们应该将axios.defaults.baseURL = "http://localhost:8080"写成axios.defaults.baseURL = “/api”。
这样我们每次请求的路径前面都会是“/api”的形式。
这也是第一步:

第一步,设置统一访问路径

在axios.js中设置axios.defaults.baseURL = "http://localhost:8080"写成axios.defaults.baseURL = "/api"

第二步、配置跨域代理

在babel.config.js的同级目录下新建一个js文件vue.config.js
在这里插入图片描述

在其中写入如下代码:这段代码是解决跨域问题而配置的一个代理。我这里后台服务器的请求连接是http://localhost:8081,所以如果你的不是的话需要修改一下。

/**
 * 解决跨域问题
 * @type {{devServer: {proxy: {"/api": {changeOrigin: boolean, pathRewrite: {"^/api": string}, target: string}}, host: string, open: boolean}}}
 */ module.exports = { devServer: { host: 'localhost', open: true, // 自动打开浏览器 // 代理配置表,在这里可以配置特定的请求代理到对应的API接口 // 例如将'localhost:8080/api/xxx'代理到'www.example.com/api/xxx' proxy: { '/api': { // 匹配所有以 '/api'开头的请求路径 target: 'http://localhost:8081', // 代理目标的基础路径 // secure: false,  // 如果是https接口,需要配置这个参数 changeOrigin: true, // 支持跨域 pathRewrite: { // 重写路径: 去掉路径中开头的'/api' '^/api': '' } } } } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

第三步、测试请求

如我们现在要发送login登录请求,那么请求应该是这样写的:

this.$axios.post("/login") 
  • 1

二、springboot后端配置解决跨域

在springboot框架的后端想要解决跨域问题,只需要添加一个类CorsConfig,并且让它实现WebMvcConfigurer接口, 其中代码如下,一般在开发的时候直接将代码复制过去就可以了。

 import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /**
 * 解决跨域问题
 */ @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("*") .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") .allowCredentials(true) .maxAge(3600) .allowedHeaders("*"); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

以上我解决跨域的两种方法,在网上也查找了很多解决跨域的方法,但是错综复杂,经过尝试和自己研究,以上两种方法是我亲测成功的,当时前后端都配置了。

所以小伙伴们有不同的见解或者更好的方法,欢迎提出指正

我是灰小猿,我们下期见!











































蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

Vue 组件通信(父传子,子传父,跨组件传值)

前端达人

目录

一, 简单介绍组件通信

二, 详解传值方法

1.父传子 props

2.子传父 $emit

3.跨组件通信 event-bus


一, 简单介绍组件通信

        我们知道在现在的开发环境下,不管前后端开发都是组件化模块化,这是因为组件的优势无比的巨大,可以进行多次的复用增加开发效率,也可以分类鲜明,便于维护,而我今天所写的就是开发中分割成不同的组件互相传递数据和互动

        我的工作中常用地组件通信大致分为三类: 父传子 , 子传父 , 跨组件传值

        下面就来分别介绍一下 我常用的这三种传值方法

二, 详解传值方法

        父子组件的确认方法:我将 B 组件import引入到 A 组件中,那么 B 就是 A 的子组件,A 就是 B 的父组件

1.父传子 props

        简而言之,父传子就是父组件把数据传给子组件,具体就是如下,在子组件的props中定义自定义属性来待接收父组件的数据,有两种方法 如下:

        第一种,也是最推荐用的一种,以复杂类型的方式进行声明,这样存储的便是一个地址,可以和父组件的数据进行双向绑定,同步数据,虽然可以双向绑定,但是在Vue2.0中还是不可以直接在子组件中更改父组件的数据,需要用到子传父才行,这点等下会写到

        这里只是用 text 举个栗子,具体叫什么都可以哈,只是父子里面需要对应上相同

        这个 text 接收到数据后的使用方法和一般data中声明的变量一样,只是不能再子组件中改变他

子组件中:        props 定义属性接收

 
  1. <template>
  2. <div>
  3. <h2>son组件</h2>
  4. <p>props:{{ text }}</p>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. // 在此处定义props
  10. props: {
  11. // props中定义 接收父组件数据的自定义属性,叫什么都可以,我随便起了个text
  12. text: {
  13. type: String, // type 是用来规定此属性接收到的数据的数据类型
  14. default: "未传递时默认的文字" // 这个default是当这个 text 没有接收到传递的数据时的默认值
  15. }
  16. }
  17. }
  18. </script>

父组件中:        标签内 传递数据

 
  1. <template>
  2. <div id="app">
  3. <!--
  4. 这里的text就是子组件props里定义的text,这两个名字得一致
  5. 并且传递的数据也要符合 type 规定的数据类型
  6. text就是传递字符串,:text就是传递动态数据
  7. -->
  8. <Son text="我是大娃 传给子啦" />
  9. <Son :text="wenzi" />
  10. </div>
  11. </template>
  12. <script>
  13. import Son from './components/son.vue';
  14. export default {
  15. data () {
  16. return {
  17. wenzi: '我是二娃 传给子啦'
  18. }
  19. },
  20. components: {
  21. Son
  22. }
  23. }
  24. </script>

        如上 虽然我的注释写的很清楚了,但是还是在介绍一下, <Son/> 是子组件的标签,在此标签的基础上书写 子组件props 定义的属性名,并且传递参数具体对应关系和效果如下:

        如上就是第一种我最常用的父传子,其实还有一种方法,但是我一般也不用,很不方便,也贴到下边了,这个是以数组方式声明

 
  1. export default {
  2. // 在此处定义props
  3. props: ['text']
  4. }
  5. </script>

 

2.子传父 $emit

        刚刚说到了在 Vue2.0 子组件不能直接改父组件的数据,否则会报错,这个解决方法就是在子组件中发起一个 自定义事件 ,在父组件监听这个事件,并且定义一个函数来改变数据,具体操作如下:

子组件:        发起一个自定义事件,等待父组件监听到执行函数

 
  1. <template>
  2. <div>
  3. <h2>son组件</h2>
  4. <p>props:{{ text }}</p>
  5. <button @click="changeTextFn">改变文字</button>
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. // 在此处定义props
  11. props: {
  12. // props中定义 接收父组件数据的自定义属性,叫什么都可以,我随便起了个text
  13. text: {
  14. type: String, // type 是用来规定此属性接收到的数据的数据类型
  15. default: "未传递时默认的文字" // 这个default是当这个 text 没有接收到传递的数据时的默认值
  16. }
  17. },
  18. methods: {
  19. // 按钮点击事件
  20. changeTextFn () {
  21. // 发起自定义事件,名字叫什么都行,第一个参数是事件名,之后再跟着的都是传递的参数
  22. this.$emit('changeFn', '我想变成三娃')
  23. }
  24. }
  25. }
  26. </script>

        我先在原有的代码上添加了一个<button>按钮,在点击调用的函数中,通过 $emit 来发起事件并且可以传递参数

格式:        this.$emit('changeFn', '我想变成三娃') 

格式:        this.$emit('自定义事件名', 传递的参数) 

 

父组件:        行内监听子组件的 自定义事件名(函数上不用写参数,在 methods 中直接写形参就行)

 
  1. <template>
  2. <div id="app">
  3. <Son :text="wenzi" @changeFn="changeFn" />
  4. </div>
  5. </template>
  6. <script>
  7. import Son from './components/son.vue';
  8. export default {
  9. data () {
  10. return {
  11. wenzi: '我是二娃 传给子啦'
  12. }
  13. },
  14. components: {
  15. Son
  16. },
  17. methods: {
  18. // 监听子组件自定义事件
  19. changeFn (newText) {
  20. // 这里的形参接受到的就是子组件中 第二个参数传递的数值
  21. this.wenzi = newText
  22. }
  23. }
  24. }
  25. </script>

对应关系和效果图如下:

 

 

 

3.跨组件通信 event-bus

        如果两个组件的关系非常的复杂或者没有未产生直接联系,那么通过父子组件通讯是非常麻烦的。这时候可以使用通用的组件通讯方案:事件总线(event-bus)

        按照我的习惯,我会将事件总线创建到 main.js 中,这个使用原理是将bus挂载到Vue原型上,这样就可以保证所有的组件都能通过 this.bus 访问到事件总线,从而通过同一个事件总线监听同一个事件,具体原理和父子传参差不多,都是 $emit 传递数据, 只不过接收变成了$on 

        我这次以送礼物举例用了两个关系不大的组件 分别是 男组件 和 女组件 (随便起的名)具体如下图:

发送数据 男组件:   

    this.bus.$emit('自定义事件名',传递的参数) 

 
  1. <template>
  2. <div>
  3. <h1>男组件</h1>
  4. <button @click="sendGiftFn">送礼物</button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. data () {
  10. return {
  11. gift: '玫瑰花'
  12. }
  13. },
  14. methods: {
  15. sendGiftFn () {
  16. // 通过 bus 事件总线发起 自定义事件,并且传递参数(第一个是事件名,第二个开始是参数)
  17. this.bus.$emit('sendMessage', this.gift)
  18. }
  19. }
  20. }
  21. </script>

接收数据 女组件:         

 this.bus.$on('监听的事件名',(e)=>{ e这个形参所接收的就是监听事件所携带的参数数据 }) 

 
  1. <template>
  2. <div>
  3. <h1>女组件</h1>
  4. <p>来自男组件的礼物:{{ info }}</p>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. data () {
  10. return {
  11. info: ""
  12. }
  13. },
  14. created () {
  15. // e 就是 sendMessage 这个事件所传递的数据
  16. this.bus.$on("sendMessage", (e) => {
  17. this.info = e;
  18. });
  19. }
  20. }
  21. </script>
  22. <style>
  23. </style>

具体效果如下:

 

综上所述,就是我在工作中总结出来的一些组建通信的方法,希望您看到这里会有所收获

蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

JavaScript作用域

前端达人

  • 作用域简介

  • JavaScript 作用域:就是代码名字,在某个范围内起的作用和效果。目的是为了提高程序的可靠性,减少命名冲突;

  • 作用域是可访问变量的集合。

  • 在 JavaScript 中, 对象和函数同样也是变量。

  • 在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。

  • JavaScript 函数作用域: 作用域在函数内修改。

  •  变量的作用域:根据作用域的不同我们的变量可以分为全局变量和局部变量

  • 局部作用域

    
                        
    1. function fn() {
    2.     var str = '我是一个局部作用域';
    3. }
    4. console.log(str);    // 这时是访问不到的
    5. // 局部变量:在局部作用域下的变量   或者在函数内部的变量就是局部变量
    6. // 注意:函数的形参也可以看做是局部变量
    7. function fun(aru) {
    8.     var num1 = 50; // num1就是局部变量  只能在函数内部使用
    9.     console.log(num1); // 在这里使用是正确的 但是在函数外面使用报错
    10.     num2 = 70;
    11.     console.log(num2); // num2在这里可以正常输出
    12.     console.log(aru);
    13.     // 首先在fun括号里面传入一个hello 然后在函数内部输出是正确的但是在函数外部输出是错误的
    14. }
    15. //fun(); 
    16. fun('hello');
    17. //console.log(num1);// 报错 num1是局部变量
    18. console.log(num2); // 这里可以输出num2是因为num2是特殊的全局变量
  • 全局作用域:

    全局变量:在全局作用域下的变量称为全局变量,在全局下都可以使用
    // 注意:如果在函数内部没有声明直接赋值的变量也属于全局变量
     

    
                        
    1. var num = 10; //num就是一个全局变量
    2. console.log(num);
    3. function fn() {
    4.     console.log('全局变量在函数内部也可以使用' + num);
    5. }
    6. fn();
  • 作用域链

  • 作用域链:内部函数访问外部函数的变量,采取的是链式查找的方式决定取哪个值 这种结构我们称为作用域链 就近原则

  • 
                        
    1. var num = 10;
    2. function fn() { //外部函数
    3.     var num = 20;
    4.     function fun() { //内部函数
    5.         console.log(num);
    6.     }
    7.     fun();
    8. }
    9. fn();
  • 作用域链总结:

  • 内部函数访问外部函数的时候,采取的是链式查找的方式,一层一层往外查找

  • 先是查找外一层,有没有,没有在往外接着查找,找到了我就输出相应的结果

  • 没有的话继续往上找就可以了,所以这个方法,我们称为作用域链

  • 简单总结就是就近原则,谁离我近我就执行谁


蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

前端脚手架的执行原理

前端达人

最近收到几位老师留言,提到一些脚手架相关的问题,跟着自己浅显的理解,以vue脚手架在windows系统上的执行为例做个分析。

正题之前,先说几个概念

脚手架的本质:运行在操作系统上node客户端里的可执行程序。

脚手架做了哪些工作?一般脚手架的工作内容主要包括三方面:

  1. 创建项目+通用代码: 埋点、http请求、工具方法、组件库。
  2. git操作: 创建仓库、代码冲突、远程代码同步、创建版本、发布打tag。
  3. 构建+发布上线: 依赖安装和构建、资源上传CDN、域名绑定、测试\正是服务器。

脚手架给我们带来哪些好处?提升前端研发效能!(就这么一句空话~~)从其为我们带来的最终体验上来讲,是实现研发过程的:

  1. 自动化:项目重复代码的copy、git操作、发布上线操作;
  2. 标准化:项目创建、git flow、发布流程、回滚流程;
  3. 数据化:使研发过程系统化、数据化、使得研发过程可量化。

脚手架的命令执行

vue create csjName –g
  1. vue 是脚手架名称
  2. create 是command,脚手架中已注册的命令
  3. csjName 是params,命令的参数
  4. –g 是options,命令的配置
  5. 一般options后也会有参数,我们称之为配置参数,上面命令其实是省略了true
    vue create csjName –g true

下面说一下vue脚手架的执行过程

环境要求,已安装node

先来思考一个问题:

我们安装vue脚手架时,安装的是@vue/cli

npm install @vue/cli –g

为什么创建项目的时候用的却是vue

vue create projectName

咱们先看 npm install @vue/cli –g命令完成拉资源后,在操作系统中都做了什么。

命令执行完成后,咱们切换到D:\mysoft\node\node_global(这个是自己安装node时设置的全局npm包的安装路径,并且已配置到环境变量中,不清楚的老师可以去熟悉一下node的安装教程),发现此路径下已经生成了一个cmd命令vue.cmd,因为此路径已配置到环境变量中,所以在cmd我们必然可以直接输入vue来执行vue.cmd。

那么vue.cmd文件中又执行了什么?打开vue.cmd

可以看到,其实它是去调用了vue脚手架资源路径下的vue.js文件

正如我们在这个路径下执行

node vue.js create csjName

是一样的。脚手架的命令及其参数的注册与解析都在此文件中完成。具体的代码逻辑不再深入讲了,因为我也没看。。。。。

再来思考个问题,在完成脚手架资源的下载后,为什么会在D:\mysoft\node\node_global下自动生成一个vue.cmd?我们能不能自定义这个脚手架的名字?

其实每个脚手架都是npm项目,vue.cmd是在此npm项目的package.json中配置的,我们也可以对其自定义修改。

欲修改脚手架名称,直接去D:\mysoft\node\node_global下重命名vue.cmd即可。如果是自己的脚手架,可在npm项目内的package.json中通过上述配置,指定脚手架的名称。

补充

另外在linux或mac系统中,其实node\node_global下并未生成vue.cmd,而是生成了一个叫做vue软链接,并且链向了node_global\node_modules\@vue\cli下的vue.js。

而且在linux和mac系统中,并未使用node vue.js,而是直接执行了vue.js那是因为在vue.js顶部已通过Shebang声明当前文件默认使用系统中环境变量/usr/bin/env 下的node解释器执行。此语法在windows系统中无效。

以上是对vue脚手架在windows中执行过程的浅显理解。不到之处,还请指正~~

最后安利一个自己已发布的npm项目csjtools,旨在打造一个前端通用的工具库,就是自己平常封装的js工具函数,如对timeout的异步封装、对storage的面向对象的封装、对日期格式的转换、还有对象之间的深比较等,目前工具还不够丰富,欢迎大家一起使用&完善,一个人的力量很小~~

npm install csjtools -g 


蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

Vue的防抖和节流(接口频繁调用如何处理)

前端达人

首先描述一下我所使用的业务场景:系统有一个批量审批的功能,每个审批的流程需要根据提交的用户实时的反馈回去进去用户页面的刷新,如果一个用户同时有多个流程被审批通过,前端会向服务端频繁的多次调用同一个接口,造成服务器压力过大和页面卡顿,非常影响用户体验。
目标:需要短时间内向服务端频繁调用接口时只去调用最后一次的接口。(防抖)

防抖和节流的区别:主要体现在执行次数上的区别,比如我们写一个200ms的延迟时间,节流就是每200ms执行一次,而抖动是只有在最后一次事件的200ms内调用一次回调函数。
防抖和节流都可以用于 mousemove、scroll、resize、input、click等事件,他们的区别在于防抖只会在连续的事件周期结束时执行一次,而节流会在事件周期内按间隔时间有规律的执行多次。

防抖 debounce

当事件被频繁触发时,在一定的时间内再去执行回调函数,如果在等待期间再次被触发,则重新计时,直至整个等待期间没有新的事件被触发,执行回调函数。

举个例子:一个点击事件,为了防止用户重复发起请求,如果用户在三秒内多次发生点击事件,点击事件将只执行一次,第一次和第二次点击的间隔只要在三秒钟内就会重置这个等待时间,第二次和第三次之间的最大等待时间也是三秒,如果第二次点击事件发生后的三秒内没有新的点击事件产生,第二次点击后的三秒就会调用回调函数。

可以直接引用loadsh的debounce方法来实现函数防抖,也可以自己写一个防抖函数(利用定时器)

  1. 引用loadsh

这里先给一个中文文档的地址:https://www.lodashjs.com/docs/lodash.debounce
在vue3.x中也推荐了这种方式:https://v3.vuejs.org/guide/data-methods.html#methods
有多种引用方式,这里我直接采用npm的方式

npm i --save lodash 
  • 1

使用loadsh的debounce方法

<el-button id="myBtn" type="goon" icon="el-icon-search" @click="test">点击事件</el-button> 
  • 1
let _ = require('lodash'); _.debounce(fun,ms,options) fun: 回调函数
ms:等待时间,毫秒
options:选项对象 
  • 1
  • 2
  • 3
  • 4
  • 5

注意:这里点击事件要写成test: 的形式,test()这样是不生效的

import debounce from 'lodash/debounce' methods:{ test:debounce(()=>{ console.log("防抖函数执行",) },3000) } //或者下面这种写法 document.getElementById("myBtn").addEventListener('click', debounce(function (event) { console.log("防抖函数执行",) }, 3000)) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. 自定义防抖函数
<el-button type="goon" icon="el-icon-search" @click="test">点击事件</el-button> 
  • 1
data:{ timer:null }, methods:{ //在最后一次点击三秒后才会触发一次点击事件 test(){ clearTimeout(this.timer) //自定义个定时器三秒后执行,一旦有新的事件发生会将这个定时器清除重新创建一个,只有三秒内不出现事件这个定时器才不会被销毁重构 this.timer = setTimeout(()=>{ console.log("防抖执行,这里就是你需要执行的操作") },3000) } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

节流 throttle

在规定的时间内只触发一次回调函数,在规定时间内多次触发函数,只会执行一次

举个例子:一个点击事件,你设定了节流的延迟时间为一秒钟,那么在你一直点击的情况下,每隔一秒会触发一次这个事件,直到你的点击停止,这个不会累积,比如一秒钟内点击了五次,然后不再点击时,事件也只会触发一次而不会累积到触发五次,这种累积的可以采用定时器实现。

节流一般多用于监听输入框和滚动条,同样的在我们的loadsh中也有写好的节流的函数throttle,使用方法和上面防抖类似,这里就不详细写了,主要写一下 自定义的节流函数。

throttle(fun, ms,options) fun:需要节流的回调函数
ms:等待时间
options:额外配置项 
  • 1
  • 2
  • 3
  • 4

自定义节流函数:
原理就是用时间戳判断是否到了回调的执行时间,记录上次执行的时间戳,然后每次触发 事件执行回调,回调里边判断当前时间戳距离上一次执行时间戳的间隔是否已经到达规定的时间,如果是就执行,并且会更新上次执行的时间戳。
下面是我写的一个简单的例子,可以根据自己需求进行修改

data:{ //这里我直接页面创建时定义了一个初始的变量,保存上一次函数执行的时间 lastTime:new Date() }, methods:{ //fun 代表要执行的函数,需要被节流的函数 throttle(fun){ //函数执行时的时间 let now = new Date() console.log("now",now) console.log("lastTime",this.lastTime) //两次调用的时间差 if (now - this.lastTime > 1000){ fun() //调用成功,上一次调用时间值修改 this.lastTime = now } }, test(){ this.throttle(function (){ //1000ms内无论点击多少下,只会调用一次 console.log("节流函数调用,时间1000ms") }) }, } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

image.png

如果项目多次用到可以将以上的方法封装成一个工具类。

参考文章:https://www.jb51.net/article/161713.htm














蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

ES6——数组扩展 ... Array.from() Array.of() flat() reduce()

前端达人

1.扩展运算符…

ES6——扩展运算符…

2.Array.from()

将两类对象转为真正的数组:类数组(querrySelectAll)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)

类数组

1.赋给length属性的对象

 //将类数组转化为真正的数组 let k={ 0:'a', 1:'b', length:2 //没有length属性就不行 } console.log(Array.from(k)); //['a', 'b'] 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.字符串也有length属性,它也是类数组

 let str='hello'; console.log(Array.from(str)); // ['h', 'e', 'l', 'l', 'o'] 
  • 1
  • 2

3.参数如果是真正的数组 则返回一个全新数组

 let s1=[1,2,3]; let s2=Array.from(s1); console.log(s2==s1); //false 
  • 1
  • 2
  • 3

3.Array.of()

一组值,转换为数组

Array.of(3, 11, 8) // [3,11,8] Array.of(3) // [3] Array.of(3).length // 1 
  • 1
  • 2
  • 3

这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。

只有当参数个数不少于 2 个时,Array()才会返回由参数组成的新数组

Array() // [] Array(3) // [, , ,] Array(3, 11, 8) // [3, 11, 8] 
  • 1
  • 2
  • 3

4.find() 和 findIndex()

find方法,用于找出第一个符合条件的数组成员

 var result1=[1,2,3,4].find(function (item) { return item%2==0; }) console.log(result1); //2 
  • 1
  • 2
  • 3
  • 4

findIndex方法,返回第一个符合条件的数组成员的位置。
如果所有成员都不符合条件,则返回-1

 var result1=[1,2,3,4].findIndex(function (item) { return item%2==0; }) console.log(result1); //1 
  • 1
  • 2
  • 3
  • 4

5.fill() 填充数组

使用给定值,填充一个数组

console.log(new Array(5).fill('a')); //['a', 'a', 'a', 'a', 'a'] 
  • 1

fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。

['a', 'b', 'c'].fill(7, 1, 2) // ['a', 7, 'c'] 
  • 1

6.数组实例的 entries(),keys() 和 values()

Set,Map,Object中都有这些方法

entries(),keys()和values()——用于遍历数组。
它们都返回一个遍历器对象,可以用for…of循环进行遍历
唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。

 let yes=[1,2,3,4]; console.log(yes.keys()); //Array Iterator {} console.log(yes.values()); //Array Iterator {} console.log(yes.entries()); //Array Iterator {} 
  • 1
  • 2
  • 3
  • 4
 let yes=[1,2,3,4]; for(let key of yes.keys()){ console.log(key); //0 1 2 3 } for(let key of yes.values()){ console.log(key); //1 2 3 4 } for(let [key,value] of yes.entries()){ console.log(key,value); //0 1 //1 2 //2 3 //3 4 } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

7.includes()

console.log([1, 2, 3].includes(1)); //true console.log([1, 2, 3].includes(1,1)); //false 从1号索引开始找 
  • 1
  • 2

8.flat()

将嵌套的数组“拉平”,变成一维的数组。
该方法返回一个新数组,对原数据没有影响

//默认只能拉平一层 console.log([1, 2, [3, 4]].flat()); //[1, 2, 3, 4] //如果拉平多层 设置层数 console.log([1, 2, [3, [4, 5]]].flat(2)); // [1, 2, 3, 4, 5] //如果层数太多 设置Infinity console.log([1, 2, [3, 4, [5, 6, [7, 8]]]].flat(Infinity)); //[1, 2, 3, 4, 5, 6, 7, 8] 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

9.reduce()

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。对空数组是不会执行回调函数的。

1.计算数组总和

var num = [1,2,3,4,5]; var res = num.reduce(function(total,num){ return total+num; //return total + Math.round(num);//对数组元素四舍五入并计算总和 },0); console.log(res); //15 //num.reduce((total,num) => total += num, 0); //没有初始值initialValue(即上面例子中的0),当数组为0时会抛出异常提示reduce函数没有初始值,所以为兼容性一般加上initialValue 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.合并二维数组

var red = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) { return a.concat(b); }, []); console.log(red); //[0, 1, 2, 3, 4, 5] 
  • 1
  • 2
  • 3
  • 4

3.统计一个数组中有多少个不重复的单词
reduce()函数










蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

Vue的设计理念

前端达人

目录

Mvvm模型

Vue中的Mvvm实现原理

自己实现双向数据绑定的示例

Vue与模板引Thymeleaf擎对比

显示变量值(Vue)

 显示变量值(Thymeleaf)

替换Html(Vue)

替换Html(Thymeleaf)

绑定属性(Vue)

绑定属性(Thymeleaf)

隐藏显示区块(Vue)

隐藏显示区块(Thymeleaf)

遍历列表数据-带索引(Vue)

 遍历列表数据-带索引(Thymeleaf)

引入其他文件内容(vue)

引入其他文件内容(Thymeleaf)

Vue的页面定义基石-Options API

Vue中的代理运用

nginx反向代理

vue代理(正向代理)

Vue特性能力-filter


Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合

Mvvm模型

MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自动传递给 View,即所谓的数据双向绑定。
Vue.js 是一个提供了 MVVM 风格的双向数据绑定的 Javascript 库,专注于View 层。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel负责连接 View 和 Model,保证视图和数据的一致性,这种轻量级的架构让前端开发更加高效、便捷。

Vue中的Mvvm实现原理

Vue.js的实现方式,对数据(Model)进行劫持,当数据变动时,数据会出发劫持时绑定的方法,对视图进行更新。

这里有两个方向: 

1、数据流向视图:数据变动时,能自动更新Dom节点的内容。此功能是通过数据劫持实现的,对数据(Model)进行劫持,当数据变动时,会调用劫持时绑定的方法,对视图进行更新。

2、视图流向数据:如输入框input内容发生变动时,input对应的数据也会发生变动。此功能是通过监听Dom事件实现的。当用户在输入框中输入文字(即inputkeyup事件发生时),vue会监听到这个事件,找到对应的数据模型变量,修改变量值。

vue中双向数据绑定的示例


  1. <div id="app-6">
  2. <p>{{ message }}</p>
  3. <input v-model="message">
  4. </div>

  1. var app6 = new Vue({
  2. el: '#app-6',
  3. data: {
  4. message: 'Hello Vue!'
  5. }
  6. })

自己实现双向数据绑定的示例


  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <title>双向绑定demoo</title>
  5. <meta charset="UTF-8">
  6. </head>
  7. <body>
  8. <div id="app">
  9. <input type="text" id="txt">
  10. <p id="show-txt"></p>
  11. </div>
  12. </body>
  13. <script>
  14. var model={}
  15. Object.defineProperty(model,'txt',{
  16. _txt: "",
  17. get:function(){
  18. return _txt
  19. },
  20. set:function(newValue){
  21. _txt = newValue
  22. document.getElementById('txt').value = newValue
  23. document.getElementById('show-txt').innerHTML = newValue
  24. }
  25. })
  26. document.addEventListener('keyup',function(e){
  27. model.txt = e.target.value
  28. })
  29. </script>
  30. </html>

这里要讲到一个关键函数

Object.defineProperty 

Object.defineProperty 需要三个参数(object , propName , descriptor)

1 object 对象 => 给谁加
2 propName 属性名 => 要加的属性的名字 【类型:String】
3 descriptor 属性描述 => 加的这个属性有什么样的特性【类型:Object】

descriptor 属性描述

get一个给属性提供getter的方法,如果没有getter则为undefined。该方法返回值被用作属性值。默认为undefined
set一个给属性提供setter的方法,如果没有setter则为undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认值为undefined

Vue与模板引Thymeleaf擎对比

显示变量值(Vue)


  1. <div id="app">
  2. {{ message }}
  3. </div>

 显示变量值(Thymeleaf)


  1. <div id="app" th:text="${message}">
  2. </div>

替换Html(Vue)


  1. <div id="app" v-html="content">
  2. </div>

替换Html(Thymeleaf)


  1. <div id="app" th:html="${content}">
  2. </div>

绑定属性(Vue)

<img :src="imgUrl" :id="newId"/>

绑定属性(Thymeleaf)

<img th:attr="id=${newId},src=${imgUrl}"/>

隐藏显示区块(Vue)


  1. <div id="app" v-if="show">
  2. 这是一个区块
  3. </div>

隐藏显示区块(Thymeleaf)


  1. <div id="app" th:if="${show}">
  2. 这是一个区块
  3. </div>

遍历列表数据-带索引(Vue)


  1. <ul id="app">
  2. <li v-for="(item, index) in dataList">
  3. {{ index }} - {{ item.message }}
  4. </li>
  5. </ul>

 遍历列表数据-带索引(Thymeleaf)


  1. <ul id="app">
  2. <li th:each="item, stat: ${dataList}">
  3. {{ stat.index }} - {{ item.message }}
  4. </li>
  5. </ul>

引入其他文件内容(vue)

在vue中,可复用的单元块被称为组件,定义组件


  1. <template>
  2. <button v-on:click="count++">You clicked me {{ count }} times.</button>
  3. </template>
  4. <script>
  5. export default {
  6. name: "button-counter"
  7. data(){
  8. count: 0
  9. }
  10. }
  11. </script>

 引入组件


  1. <div id="components-demo">
  2. <button-counter></button-counter>
  3. </div>

引入其他文件内容(Thymeleaf)

被导入模块index.html:


  1. <div th:fragment="head">
  2. 这是网页头
  3. </div>

在其它页面导入index.html中的head模块:

<div th:include="index::head"></div>

由此可见在Html层面上来讲,vue和后台的模板引擎,整个设计方向是一样。都是使用特定属性标签,来描述如何把数据映射到视图上。

Vue的页面定义基石-Options API

Options API,即大家常说的选项API,即以vue为后缀的文件,通过定义methodscomputedwatchdata等属性与方法,共同处理页面逻辑

可以看到Options代码编写方式,如果是组件状态,则写在data属性上,如果是方法,则写在methods属性上...

这种形式的页面定义类似一个配置文件,定义了页面的数据模型和行为

Vue中的代理运用

代理服务器:所谓代理服务器就是位于发起请求的客户端与原始服务器端之间的一台跳板服务器,是以正向代理可以隐藏客户端,反向代理可以隐藏原始服务器。

代理分为正向代理和反向代理,下面就以我们实际使用中的示例讲解下这两种代理方式的区别。

nginx反向代理

这样对于浏览器而言,浏览器只需要访问代理服务器,就可以达到同时访问两个网站的目的

 

我们看下实际场景下的nginx的配置 


  1. server {
  2. listen 4503;
  3. server_name vue.izkml.com;
  4. access_log "pipe:rollback logs/gov-manage-new-vue/access_log interval=1d baknum=7 maxsize=2G" main;
  5. # 接口代理
  6. location /api {
  7. #去除 /api前缀
  8. rewrite ^.+api/?(.*)$ /$1 break;
  9. # 转发到 117.71.53.199:50020端口上
  10. proxy_pass http://117.71.53.199:50020;
  11. proxy_buffering off;
  12. }
  13. # 页面文件代理
  14. location / {
  15. # 直接去本地文件读取文件路径
  16. root html/gov-task-supervison;
  17. index index.html index.htm;
  18. if (!-e $request_filename) {
  19. rewrite ^/(.*) /index.html last;
  20. break;
  21. }
  22. }
  23. }

其中可以看到,主要分为接口代理和页面代理两部分
1. 如果是/api前缀的请求,则去除/api前缀,转发到后台网关端口上
2. 其他情况下,请求的为页面内容,在html/gov-task-supervison文件夹中读取文件内容

vue代理(正向代理)

 


  1. devServer: { // 支持webPack-dev-server的所有选项
  2. port: 8888, // 端口号
  3. host: '0.0.0.0',
  4. https: false,
  5. open: true, //配置自动启动浏览器
  6. proxy: {
  7. '/api': {
  8. // 转发地址
  9. target: 'http://117.71.53.199:50020', //测试环境
  10. changeOrigin: true,
  11. ws: true,
  12. // 去除/api前缀
  13. pathRewrite: {
  14. '^/api': ''
  15. }
  16. }
  17. }
  18. }

这里主要看的是proxy字段,其中定义了规则

1. 如果是/api前缀的请求,则去除/api前缀,转发到后台网关端口上
2. 其他情况下,请求的为页面内容,直接读取本地项目路径下面的页面内容 **(隐式包含)**

Vue特性能力-filter

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化

应用场景: 前端常量翻译


  1. <el-tag v-if="scope.row.status" class="round" size="small" >
  2. {{scope.row.status | CodeMaster('TASK_STATUS')}}
  3. </el-tag>

  1. Vue.filter('CodeMaster', function (value, type) {
  2. return Vue.prototype.$codeMaster.getCodeValue(type, value);
  3. })

在上面的代码中,我们在模板html中,添加了filter的调用,并传入了一个参数。
在vue进行html生成的过程中,会调用相应的filter,根据自定义的规则,完成文本格式化操作。




蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

JavaScript防抖与节流,深入浅出,一本正经讲透彻

前端达人

目录

一、函数防抖(debounce)

1. 什么是防抖?

二.、函数节流

2.1 定时器实现

2.2 时间戳实现

2.3 时间戳+定时器

最后 


一、函数防抖(debounce)

1. 什么是防抖?

函数防抖在频繁触发某一个事件时,一段时间内不再触发该事件后才会去调用对应的回调函数,在设定间隔时间内如果下一次事件被触发, 那么就重新开始定时器,直到事件触发结束。

规定时间内没有继续触发事件的前提下,再去调用事件处理函数;

具体如下面的例子所示:


  1. /*定义防抖函数
  2. * func:传入一个函数,事件不再持续触发时会调用该函数
  3. * delay:定义持续多久后执行传入的回调函数
  4. * */
  5. function debounce(func,delay) {
  6. let timer = null // 用于保存定时器
  7. return function (...args) {
  8. // 如果定时器存在,清除定时器,随后重新设置timer
  9. if(timer !== null) clearTimeout(timer)
  10. timer = setTimeout(func, delay) // 超过delay为接收到事件会调用这里的func 必要的额时候可以修改func的this指向 由于timer对外部存在引用,因此不会被销毁
  11. }
  12. }
  13. /*事件处理函数*/
  14. function testDeBounce(){
  15. console.log('你看我执行了几次??')
  16. }
  17. // 接收debounce返回的函数
  18. const temp = debounce(testDeBounce(),1000)
  19. /*绑定事件,测试防抖函数*/
  20. window.addEventListener('scroll',()=>{
  21. temp()
  22. }); // 这样写最少调用一次事件处理函数,最多也不会多余下面的写法执行的次数
  23. window.addEventListener('scroll', testDeBounce); // 如果这样写的话,每当页面滚动就会调用事件处理函数
  • 总结一下思路

    1.定义一个节流函数

    2.函数内部使用一个变量保存定时器

    3.返回一个函数,函数内部定义:如果定时器已经存在就清除定时器,重新设置定时器

    4.定义一个变量来接收debounce返回的函数

    5.在事件的回调函数中直接调用上一步的变量接收的方法


二.、函数节流

函数节流在事件持续触发的前提下,保证一定时间段内只调用一次事件处理函数,就是函数节流;

函数节流实现的方式定时器、时间戳、定时器+时间戳;

2.1 定时器实现

思路

1.定义节流函数throttle

2.定义timer保存定时器

3.返回一个函数。函数内部定义:如果定时器不存在,设置定时器,间隔某一时间后将timer设置为null,如果在这之前事件再次触发,则定时器中的回调无效

<button>这是一个孤独的按钮</button> 

  1. /*
  2. * 定义定时器节流函数
  3. * func:传入事件处理函数
  4. * delay:在delay指定的时间内定时器回调无效
  5. * */
  6. function throttle(func,delay) {
  7. let timer = null
  8. const context = this
  9. return function(...args){
  10. // 如果定时器不存在
  11. if(!timer){
  12. timer = setTimeout(()=>{
  13. func.apply(context,args) // 考虑返回的函数调用的环境,因此这里不直接使用this
  14. timer = null // delay之后清除定时器
  15. },delay)
  16. }
  17. }
  18. }
  19. function test() {
  20. console.log('啊啊啊!')
  21. }
  22. const temp = throttle(test,1000)
  23. document.querySelector('button').addEventListener('click',()=>{
  24. temp()
  25. })

2.2 时间戳实现


  1. var throttle = function(func, delay) {
  2. var prev = Date.now();
  3. return function() {
  4. var context = this;
  5. var args = arguments;
  6. var now = Date.now();
  7. if (now - prev >= delay) {
  8. func.apply(context, args);
  9. prev = Date.now();
  10. }
  11. }
  12. }
  13. function handle() {
  14. console.log(Math.random());
  15. }
  16. window.addEventListener('scroll', throttle(handle, 1000));

2.3 时间戳+定时器


  1. // 节流throttle代码(时间戳+定时器):
  2. var throttle = function(func, delay) {
  3. var timer = null;
  4. var startTime = Date.now();
  5. return function() {
  6. var curTime = Date.now();
  7. var remaining = delay - (curTime - startTime);
  8. var context = this;
  9. var args = arguments;
  10. clearTimeout(timer);
  11. if (remaining <= 0) {
  12. func.apply(context, args);
  13. startTime = Date.now();
  14. } else {
  15. timer = setTimeout(func, remaining);
  16. }
  17. }
  18. }
  19. function handle() {
  20. console.log(Math.random());
  21. }
  22. window.addEventListener('scroll', throttle(handle, 1000));

最后 

想跟博主交朋友的可以查找,公_号❤:前端老实人,跟博主一起探讨学习哦❤


蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

分享此文一切功德,皆悉回向给文章原作者及众读者.

转自:csdn
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档