浅谈vue2的12种组件通信方式及理解
重新梳理了一下,个人认为Vue中组件通信思想与React一致,都是单向数据流,高阶流向低阶(父传子),子组件只可通知父组件,此时数据还是在父级变更而不是发生流动。
1. props
高频使用
父组件向子组件传递参数。 Vue文档: props
2. $emit
高频使用
子组件通知父组件执行对应函数,可携带参数。 Vue文档: $emit
3. $refs
高频使用,也可用在DOM元素操作
通信上属于父组件向子组件传递。通过给子组件设置ref属性,使用 this.$refs 对象来获取实例,即可直接访问及调用子组件上的属性和方法。 Vue文档: refs
4. Vuex 状态管理器
需注意场景使用,可以很好地满足复杂数据交互,在SPA应用中无障碍通信,但频繁使用会增加代码耦合度。
主要以State、Getters、Mutations、Actions四个核心组成,约定了对数据的变更只在 Mutations 中,以 store.commit触发,异步操作则放在 Actions 中,以 store.dispatch 触发。 Vuex官网文档
5. $root、$parent、$chi ...
探索响应式数据原理,Proxy与reflect
首先上一段代码:
1234const obj = { age: 1 } // 定义一个对象let age = obj.age // 将对象的age属性赋值给一个变量obj.age++ // 对象的age属性发生了变化console.log(`age=${age}`, obj); // 输出结果: age = 1 {age: 2}
在obj的age属性变化时,变量age如果也随之变化,通常就需要定义一个函数赋予改变逻辑,在每次变化时手动执行一下函数。下面将以vue3中的响应式设计作为参考,来实现一个能自动响应方法。
创建Demo在Vue3中,数据响应模块被独立拆分了出来,现在我们可以随意创建一个node项目,然后npm或yarn安装包@vue/reactivity,这个包中有两个关键函数,reactive 和 effect,分别是创建一个响应式的对象和数据发生改变时的监听方法:
使用包引入的函数,修改了上面的例子,满足了响应式需求,外部定义的变量跟随对象一起改变,打印出两个数值一致:
1234567891011121314c ...
从零开始实现一个Vuex状态管理器
前言先vue-cli工具直接创建一个项目,勾选Vuex,其他随意:
创建完毕自动安装依赖,之后启动项目,熟悉的helloworld ~ 简单写个demo运行看看,后面会逐步实现一个myVuex,来达到相同的期望运行结果:
src/store/index.js :
123456789101112131415161718192021222324252627import Vue from "vue";import Vuex from "vuex";Vue.use(Vuex);export default new Vuex.Store({ state: { age: 7 }, getters: { // 不用多说 getAge(state) { return state.age } }, mutations: { // vuex约定了对state的操作函数都放在这里,使用commit方法触发 changeAge(state, data) ...
从零开始基于React服务端渲染&同构
1. 概念分析:服务端渲染(SSR)
更好的⾸屏性能
更利于 SEO,爬虫可以直接抓取已渲染的内容
客户端渲染
前后分离,⻚⾯的交互
同构:服务端和客户端都可以运⾏的同⼀套代码
同一套代码,复用率,可维护性增强
同时具有SSR与前后端分离的优势,利于 SEO 优化
更好的性能与更好的用户体验
2. 架构思路及要点React提供了服务器渲染的各种API,可快速满足同构需求。同一份代码要在服务端与客户端各执行一次,首屏加载完服务端渲染的页面后,客户端紧接着继续执行并重新渲染页面,接管后续的页面交互。
3. 同构关键点所谓同一份代码同时运行服务端和客户端,其实可复用的基本为组件,服务端与客户端的差异无法完全被抹平,而React的好处就是对服务端构建提供了不少解决方案。
1. 路由不同客户端使用:<BrowserRouter /> 服务端使用:<StaticRouter />
2. 代码的同构
接下来我们将尝试一步步从零开始实现一个React同构项目Demo。
文章参考:https://imweb.io/topic/5d2da910b17a4bd24 ...
40行代码实现一个简单Promise函数
一个遵循PromiseA+规范的函数,解决异步回调地狱问题。
Promise主要特点
Promise 会有三种状态,「进⾏中」「已完成」和「已拒绝」,进⾏中状态可以更改为已完成或已拒绝,已经更改过状态后⽆法继续更改(例如从已完成改为已拒绝)。
Promise 构造之后需要传⼊⼀个函数,它接受两个参数,执⾏第⼀个参数之后就会改变当前 promise 为「已完成」状态,执⾏ 第⼆个参数之后就会变为「已拒绝」状态。
通过 .then ⽅法,即可在上⼀个 promise 达到已完成 时继续执⾏下⼀个函数或 promise。同时通过 resolve 或 reject 时传⼊参数,即可给下⼀个函数或 promise 传⼊初始值。
已拒绝的 promise,后续可以通过 .catch ⽅法或是 .then ⽅法的第⼆个参数或是 try catch 进⾏捕获。
结构梳理1234567891011121314151617class simplePromise { constructor(handleFn) { // 构造时传入一个函数 this.status ...
一起写几个JS函数(call、防抖节流)
call函数先从改变this指向上简单实现一个方法添加到Function的原型链上:
12345Function.prototype.myCall = function (content) { content.fn = this const result = eval(`content.fn()`) return result}
这就实现了call函数核心部分,因为使用了字符串的形式,所以函数的参数部分还需要进行特殊处理:
1234567891011Function.prototype.myCall = function (content) { content.fn = this /** 处理参数 */ const args = [] for (let i = 1; i < arguments.length; i++) { args.push(`arguments[${i}]`) // 直接push会导致强转字符串时出现:[] } /** */ ...
JS面向对象编程及原型继承全面解析
面向对象编程的特点
封装:使用对象的人无需考虑内部实现,只考虑功能的使用。
继承:为了代码的可复用。
多态:不同对象 作用于同一操作产生不同结果。
JS如何创建对象普通方式123const A = new Object()A.attribute = '' // 定义属性A.fn = function() { } // 定义方法
工厂模式123456function Creat(attr) { // .... 同上面普通方式 return A}const aa = Creat('...')const bb = Creat('...')
存在问题:往实例化对象上层找不到父类,只能知道是一个Object
构造函数/实例12345678910function Player(name) { this.name = name this.run = function() { console.log('...'); ...
一次搞懂前端this、闭包、作用域
闭包的应用
闭包是指有权访问另外一个函数作用域中的变量的函数.可以理解为(能够读取其他函数内部变量的函数)
0. 封装私有变量123456789101112131415161718192021function Person0() { this._attackVolume = 100;}Person0.prototype = { /** ... **/};var p0 = new Person0(); console.log(p0._attackVolume); // 100// 工厂方法function Person1() { var _attackVolume = 100; return { attack() { console.log('attack ' + _attackVolume); _attackVolume++ } };}var p1 = new Pe ...
浅谈浏览器Dom事件、Ajax、Bom
0. 事件流以及事件委托机制
假设一段DOM结构如下:
12345<ul> <li> 1 </li> <li> 2 </li> <li> 3 </li></ul>
js中对body注册点击事件(也可以对ul注册点击事件)
1234567document.body.addEventListener('click', e => { console.log('捕获阶段');}, true)document.body.addEventListener('click', e => { console.log('冒泡阶段');}, false)
true表示捕获阶段触发,false表示冒泡阶段触发
如果我们为每个li赋予点击事件,会注册多个方法,但是在ul(外层父层)中只需要注册一次,利用捕获冒泡的原理,相当于每个li都能触发事件,这就是事件委 ...
那些奇怪怪的JavaScript
JS浮点数丢失精度问题10.3 - 0.2 !== 0.1 // true
JS最大数字长度1Number x = 9007199254740992 // 即2的53次方,js数字长度最大不能超过这个数值
parseInt 太小的数字会产生 bug12parseInt(0.00000000233) // 2parseInt(0.00000000456) // 4
NaN更像是一个范围,在JS中比较特殊,它并不会等于自身12const x = NaN;x !== x // true
isNaN也存在bug,ES6中对其进行了修复12isNaN('abc'); // trueNumber.isNaN('abc') // false
null的设计问题123456789101 + null // 11 ...








