提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
@TOC面试题
Vue.js(/vjuː/,或简称为Vue)是一个用于创建用户界面的开源JavaScript框架,也是一个创建单页应用的Web应用框架。2016年一项针对JavaScript的调查表明,Vue有着89%的开发者满意度。在GitHub上,该项目平均每天能收获95颗星,为Github有史以来星标数第3多的项目同时也是一款流行的JavaScript前端框架,旨在更好地组织与简化Web开发。Vue所关注的核心是MVC模式中的视图层,同时,它也能方便地获取数据更新,并通过组件内部特定的方法实现视图与模型的交互PS: Vue作者尤雨溪是在为AngularJS工作之后开发出了这一框架。他声称自己的思路是提取Angular中为自己所喜欢的部分,构建出一款相当轻量的框架最早发布于2014年2月
优点:渐进式,组件化,轻量级,虚拟dom,响应式,单页面路由,数据与视图分开
缺点:单页面不利于seo,不支持IE8以下,首屏加载时间长
使用场景:单页面应用程序,移动端
数据驱动(MVVM)
MVVM表示的是 Model-View-ViewModel
Model:模型层,负责处理业务逻辑以及和服务器端进行交互
View:视图层:负责将数据模型转化为UI展示出来,可以简单的理解为HTML页面
ViewModel:视图模型层,用来连接Model和View,是Model和View之间的通信桥梁
1.什么是组件化一句话来说就是把图形、非图形的各种逻辑均抽象为一个统一的概念(组件)来实现开发的模式,
在Vue中每一个.vue文件都可以视为一个组件
2.组件化的优势
(1)降低整个系统的耦合度,在保持接口不变的情况下,我们可以替换不同的组件快速完成需求,
例如输入框,可以替换为日历、时间、范围等组件作具体的实现
(2)调试方便,由于整个系统是通过组件组合起来的,在出现问题的时候,可以用排除法直接移除组件,
或者根据报错的组件快速定位问题,之所以能够快速定位,是因为每个组件之间低耦合,职责单一,所以逻辑会比分析整个系统要简单
(3)提高可维护性,由于每个组件的职责单一,并且组件在系统中是被复用的,所以对代码进行优化可获得系统的整体升级
插件是什么
插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:
添加全局方法或者属性。如: vue-custom-element
添加全局资源:指令/过滤器/过渡等。如 vue-touch
通过全局混入来添加一些组件选项。如vue-router
添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如vue-router
三、两者的区别
两者的区别主要表现在以下几个方面:
编写形式
注册形式
使用场景
注意的是:
注册插件的时候,需要在调用 new Vue() 启动应用之前完成
Vue.use会自动阻止多次注册相同插件,只会注册一次
#使用场景
具体的其实在插件是什么章节已经表述了,这里在总结一下
组件 (Component) 是用来构成你的 App 的业务模块,它的目标是 App.vue
插件 (Plugin) 是用来增强你的技术栈的功能模块,它的目标是 Vue 本身
简单来说,插件就是指对Vue的功能的增强或补充
Vue所有的界面事件,都是只去操作数据的,Jquery操作DOM
Vue所有界面的变动,都是根据数据自动绑定出来的,Jquery操作DOM
相同点
都有组件化思想
都支持服务器端渲染
都有Virtual DOM(虚拟dom)
数据驱动视图
都有支持native的方案:Vue的weex、React的React native
都有自己的构建工具:Vue的vue-cli、React的Create React App
#区别
数据流向的不同。react从诞生开始就推崇单向数据流,而Vue是双向数据流
数据变化的实现原理不同。react使用的是不可变数据,而Vue使用的是可变的数据
组件化通信的不同。react中我们通过使用回调函数来进行通信的,而Vue中子组件向父组件传递消息有两种方式:事件和回调函数
diff算法不同。react主要使用diff队列保存需要更新哪些DOM,得到patch树,再统一操作批量更新DOM。Vue 使用双向指针,边对比,边更新DOM
v-text – 设置文本内容,将data数据展示到视图中 纯文本
v-html – 设置文本内容,将data数据展示到视图中 可以解析html元素
v-cloak – 解决插值页面闪烁问题
v-once – 设置文本 只执行一次
v-pre – 格式化
v-slot – 插槽
v-show – 显示隐藏元素
条件渲染指令 v-if
列表渲染指令v-for
属性绑定指令v-bind
事件绑定指令v-on
双向数据绑定指令v-model
事件修饰符
prevent 阻止默认行为(例如:阻止a 连接的跳转、阻止表单的提交等)
stop 阻止事件冒泡
capture 以捕获模式触发当前的事件处理函数
once 绑定的事件只触发1次
self 只有在event.target是当前元素自身时触发事件处理函数
passive 允许默认行为
按键修饰符
.enter 回车
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space 空格
.up 上
.down 下
.left 左
.right 右
.ctrl
.alt
.shift
键盘上的abcd等等…
单页面应用(SPA) 多页面应用(MPA)
组成 一个主页面和多个页面片段 多个主页面
刷新方式 局部刷新 整页刷新
url模式 哈希模式 历史模式
SEO搜索引擎 优化 难实现, 可使用SSR方式改善 容易实现
数据传递 容易 通过url、cookie、localStorage等传递
页面切换 速度快,用户体验良好 切换加载资源,速度慢,用户体验差
维护成本 相对容易 相对复杂
#单页应用优缺点
优点:
具有桌面应用的即时性、网站的可移植性和可访问性
用户体验好、快,内容的改变不需要重新加载整个页面
良好的前后端分离,分工更明确
缺点:
不利于搜索引擎的抓取
首次渲染速度相对较慢
v-show与v-if的共同点
我们都知道在 vue 中 v-show 与 v-if 的作用效果是相同的(不含v-else),都能控制元素在页面是否显示
在用法上也是相同的
不同:
v-if : 通过操控DOM值来 实现 显示隐藏
(不适合频繁切换. 数据多不建议用if.每一次切换则重新消耗性能.乱)
v-if是惰性的,只有当条件为真时才会真正渲染标签;如果初始条件不为真,则v-if不会去渲染标签。
v-show :修改元素的display,实现显示隐藏
(适合频繁切换,在第一次渲染的时候已经消耗了性能)
v-show则无论初始条件是否成立,都会渲染标签,它仅仅做的只是简单的CSS
v-show与v-if的使用场景
v-if 与 v-show 都能控制dom元素在页面的显示
v-if 相比 v-show 开销更大的(直接操作dom节点增加与删除)
如果需要非常频繁地切换,则使用 v-show 较好
如果在运行时条件很少改变,则使用 v-if 较好
生命周期 描述
beforeCreate 组件实例被创建之初
created 组件实例已经完全创建
beforeMount 组件挂载之前
mounted 组件挂载到实例上去之后
beforeUpdate 组件数据发生变化,更新之前
updated 组件数据更新之后
beforeDestroy 组件实例销毁之前
destroyed 组件实例销毁之后
activated keep-alive 缓存的组件激活时
deactivated keep-alive 缓存的组件停用时调用
errorCaptured 捕获一个来自子孙组件的错误时被调用
每个生命周期函数的作用是什么
beforecreate:
实例已经初始化,但不能获取DOM节点。(没有data,没有el)
created:
实例已经创建,仍然不能获取DOM节点。(有data,没有el)
载入阶段:
beforemount:
模板编译完成,但还没挂载到界面上。(有data,有el)
mounted:
编译好的模板已挂载到页面中(数据和DOM都已经渲染出来)。
更新阶段:
beforeupdate:
数据发生变化立即调用,此时data中数据是最新的,但页面上数据仍然是旧的(检测到数据更新时,但DOM更新前执行)。
updated:
更新结束后执行,此时data中的值和页面上的值都是最新的。
销毁阶段:
beforedestroy:
当要销毁vue实例时,在销毁之前执行。
destroyed:
在销毁vue实例时执行。
actived
在keep-alive中使用,缓存组件激活
deactived
在keep-alive中使用,缓存组件不激活
使用场景分析
生命周期 描述
beforeCreate 执行时组件实例还未创建,通常用于插件开发中执行一些初始化任务
created 组件初始化完毕,各种数据可以使用,常用于异步数据获取
beforeMount 未执行渲染、更新,dom未创建
mounted 初始化结束,dom已创建,可用于获取访问数据和dom元素
beforeUpdate 更新前,可用于获取更新前各种状态
updated 更新后,所有状态已是最新
beforeDestroy 销毁前,可用于一些定时器或订阅的取消
destroyed 组件已销毁,作用同上
8.第一次页面加载会触发哪几个生命周期钩子函数?
beforeCreate, created, beforeMount, mounted
当v-if 与 v-for 一起使用时,v-for 比v-if 优先级高,如果连用的话会把 v-if 给每个元素都添加一下,会造成性能问题
所以不推荐v-if和v-for在同一个标签中同时使用。先有循环才能渲染
永远不要把 v-if 和 v-for 同时用在同一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断)
如果避免出现这种情况,则在外层嵌套template(页面渲染不生成dom节点),在这一层进行v-if判断,然后在内部进行v-for循环
常见的几种SPA首屏优化方式
减小入口文件积
静态资源本地缓存
UI框架按需加载
图片资源的压缩
组件重复打包
开启GZip压缩
使用SSR
减少首屏渲染时间的方法有很多,总的来讲可以分成两大部分 :资源加载优化 和 页面渲染优化
vue组件中data值不能为对象,因为对象是引用类型,每个组件的data都是内存的同一个地址,如果修改一个对象里面的数据,其他的也会被影响到,
data 如果是一个函数,每一个函数都有自己的局部作用域,他改变的话不会影响到其他的数据。
data在什么情况下是函数 在什么情况下是对象
1- 对象: 普通文件 .html
2- 函数: 组件中 .vue
为什么在组件中要是用 函数 ?
因为 多个组件数据交互时,可能会出现单个组件独立使用的数据,不需要被其他组件访问,且避免组件之间的冲突,或者重名 所以设置到函数中 指在当前组件生效 关闭此组件自动销毁
Vue.set()
Object.assign()
$forcecUpdated()
Vue.set( target, propertyName/index, value )
参数
{Object | Array} target
{string | number} propertyName/index
{any} value
返回值:设置的值
Object.assign()
直接使用Object.assign()添加到对象的新属性不会触发更新应创建一个新的对象,合并原对象和混入对象的属性
this.someObject = Object.assign({},this.someObject,{newProperty1:1,newProperty2:2 …})
$forceUpdate
如果你发现你自己需要在 Vue中做一次强制更新,99.9% 的情况,是你在某个地方做错了事
$forceUpdate迫使Vue 实例重新渲染
PS:仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
#小结
如果为对加粗样式象添加少量的新属性,可以直接采用Vue.set()
如果需要为新对象添加大量的新属性,则通过Object.assign()创建新对象
如果你实在不知道怎么操作时,可采取$forceUpdate()进行强制刷新 (不建议)
PS:vue3是用过proxy实现数据响应式的,直接动态添加新属性仍可以实现数据响应式
4.在vue开发时,改变数组或者对象的数据,什么情况页面视图没有更新?如何解决?
对于数组:
Vue 不能检测以下数组的变动:
1.当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
2.当你修改数组的长度时,例如:vm.items.length = newLength
对于对象:
Vue 不能检测到给已有对象添加的新属性:例如:vm.obj.age= 18
解决方案:对于数组可以使用 Vue.set() 或者 vm. s e t ( ) 或者 s p l i c e 例如 V u e . s e t ( v m . i t e m s , i n d e x O f I t e m , n e w V a l u e ) v m . set()或者splice 例如 Vue.set(vm.items, indexOfItem, newValue) vm. set()或者splice例如Vue.set(vm.items,indexOfItem,newValue)vm.set(vm.items, indexOfItem, newValue)
vm.items.splice(indexOfItem, 1, newValue)
对于对象:Vue.set() 或者 vm.$set()或者splice或者 Object.assign()
例如:
1)你可以添加一个新的 age 属性到嵌套的 userProfile 对象:
Vue.set(vm.userProfile, ‘age’, 27)
2)你还可以使用 vm. s e t 实例方法,它只是全局 V u e . s e t 的别名: v m . set 实例方法,它只是全局 Vue.set 的别名: vm. set实例方法,它只是全局Vue.set的别名:vm.set(vm.userProfile, ‘age’, 27)
3)有时你可能需要为已有对象赋予多个新属性,比如使用 Object.assign() 或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: ‘Vue Green’
})
1.父传子 父组件 v-bind
子组件 props
props - 对象【详细、简单】、数组
props:{
属性名:类型,
属性名:类型
}
props:[‘属性名’,‘属性名’]
props:{
属性名:{
type:类型,
required:必填项 true - 必填 false反之
default:默认值
}
}
2.子传父
子组件:this.$emit(“事件名”,参数) 触发事件
父组件:v-on:自定义事件名=“事件处理函数” @自定义事件名=“事件处理函数” 监听事件 绑定事件
3.任意组件 全局事件总线\vuex\pubsub
添加:
全局配置:main.js
beforeCreate(){
Vue.prototype.$bus=this
}
子组件:this.$bus.$emit("事件",参数)触发事件
父组件:this.$bus.$on监听事件 mounted()要写在挂载后
this.$bus.$off("事件名") 销毁之前 销毁绑定的事件
4.依赖注入:跨代传参 可以跨代传参 也可以父子传参
依赖:provide(){return{arr:[]}}: 函数 对象 返回的的都是对象 依赖当前所在组件的属性向其他组件注入
注入:inject:[‘arr’]
5. p a r e n t / parent / parent/children/$refs $parent指的是父组件实例 c h i l d r e n / children/ children/refs是子组件实例
6. $attrs & $listeners
a t t r s 获取父组件中不被 p r o p s 接收的自定义属性并且可以通过 v − b i n d = " attrs获取父组件中不被props接收的自定义属性 并且可以通过 v-bind=" attrs获取父组件中不被props接收的自定义属性并且可以通过v−bind="attrs" 传入内部组件
$listeners获取父组件中的自定义事件
vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue实例来作为它的 data选项时,Vue将遍历它的属性,用Object.defineProperty()将它们转为getter/setter。用户看不到getter/setter,但是在内部它们让Vue追踪依赖,在属性被访问和修改时通知变化。
因为vue中dom更新有延迟,所以当数据修改后 视图不能同步更新完成 这个时候就绪要等待dom更新完毕后获取新值 否则只能获取到之前的老值 想操作新值需要通过$nextTick获取新值,nextTick会在dom更新完毕后自动执行回调函数
如果想要在修改数据后立刻得到更新后的DOM结构,可以使用Vue.nextTick()
mixin(混入),提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。
本质其实就是一个js对象,它可以包含我们组件中任意功能选项,如data、components、methods、created、computed等等
我们只要将共用的功能以对象的方式传入 mixins选项中,当组件使用 mixins对象时所有mixins对象的选项都将被混入该组件本身的选项中来
在Vue中我们可以局部混入跟全局混入
使用场景
在日常的开发中,我们经常会遇到在不同的组件中经常会需要用到一些相同或者相似的代码,这些代码的功能相对独立
这时,可以通过Vue的mixin功能将相同或者相似的代码提出来
插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。通俗的说是:slot 是在父组建控制了子组件显示或隐藏相关内容。
插槽又分为三种,1.普通插槽 2.具命插槽 3.作用域插槽
1.匿名插槽 : 父组件传递 一个html结构 给子组件
(1)子组件: 插槽默认内容
(2)父组件: <子组件> html结构 子组件>
2.具名插槽 : 父组件传递 多个html结构 给子组件
(1)子组件: 给插槽添加一个name(插槽名)
插槽默认内容
(2)父组件: 使用 v-slot:插槽名 或 #插槽名
<子组件>
html结构
子组件>
3.作用域插槽: 子组件传递 数据 给父组件插槽
(1)子组件 : 给内置组件添加自定义属性
(2)父组件 : 使用 v-slot=“对象名”
普通插槽
b、具名插槽
c、作用域插槽:延长子组件的作用域范围
插槽的样式由父组件决定,内容由子组件控制
{{user.username}}
{{user.username1}}
如果列表项自身有id区分(唯一的证明)则使用即可,如果不存在,则依赖key值作为唯一标识,会导致数据冲突或者覆盖
无:key属性时,状态默认绑定的是位置; 删除所有,重新渲染,
有:key属性时,状态根据key的属性值绑定到了相应的数组元素。删除某一条不会重新渲染,节省性能,
Keep-alive 是 Vue.js 内置的一个抽象组件,用于缓存有状态组件,可以在组件切换时保留组件的状态避免重新渲染。它有以下两个作用:
缓存有状态的组件,避免组件在切换时被重新渲染;
在缓存的组件被激活时触发 activated 钩子函数,在缓存的组件被停用时触发 deactivated 钩子函数。
使用 Keep-alive 可以提高组件的性能,尤其是在组件状态比较复杂或需要较长时间计算的情况下,通过缓存组件避免重复渲染,提高应用的性能。
keep-alive是vue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM
keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们
keep-alive可以设置以下props属性:
include - 字符串或正则表达式。只有名称匹配的组件会被缓存
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存
max - 数字。最多可以缓存多少组件实例
关于keep-alive的基本用法:
使用includes和exclude: 缓存后如何获取数据 解决方案可以有以下两种:beforeRouteEnter
actived
#beforeRouteEnter
每次组件渲染的时候,都会执行beforeRouteEnter
beforeRouteEnter(to, from, next){
next(vm=>{
console.log(vm)
// 每次进入路由执行
vm.getData() // 获取数据
})
},
#actived
在keep-alive缓存的组件被激活的时候,都会执行actived钩子
activated(){
this.getData() // 获取数据
},
注意:服务器端渲染期间avtived不被调用
在vue中提供了一套为数据驱动视图更为方便的操作,这些操作被称为指令系统
我们看到的v-开头的行内属性,都是指令,不同的指令可以完成或实现不同的功能
除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令
指令使用的几种方式:
注册一个自定义指令有全局注册与局部注册
全局注册主要是通过Vue.directive方法进行注册
Vue.directive第一个参数是指令的名字(不需要写上v-前缀),第二个参数可以是对象数据,也可以是一个指令函数
// 注册一个全局自定义指令 v-focus
Vue.directive(‘focus’, {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus() // 页面加载完成之后自动让输入框获取到焦点的小功能
}
})
局部注册通过在组件options选项中设置directive属性
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus() // 页面加载完成之后自动让输入框获取到焦点的小功能
}
}
}
然后你可以在模板中任何元素上使用新的 v-focus property,如下:
概念:
虚拟DOM其实就是用一个原生的JS对象去描述一个DOM节点,实际上它只是对真实 DOM 的一层抽象。最终可以通过一系列操作使这棵树映射到真实环境上。
相当于在js与DOM之间做了一个缓存,利用patch(diff算法)对比新旧虚拟DOM记录到一个对象中按需更新, 最后创建真实的DOM
虚拟dom原理流程:
模板 ==> 渲染函数 ==> 虚拟DOM树 ==> 真实DOM
vuejs通过编译将模板(template)转成渲染函数(render),执行渲染函数可以得到一个虚拟节点树
在对 Model 进行操作的时候,会触发对应 Dep 中的 Watcher 对象。Watcher 对象会调用对应的 update 来修改视图。
虚拟 DOM 的实现原理主要包括以下 3 部分:
用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
diff 算法 — 比较两棵虚拟 DOM 树的差异;
pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。
diff 算法是一种通过同层的树节点进行比较的高效算法
其有两个特点:
比较只会在同层级进行, 不会跨层级比较
在diff比较的过程中,循环从两边向中间比较
diff 算法在很多场景下都有应用,在 vue 中,作用于虚拟 dom 渲染成真实 dom 的新旧 VNode 节点比较
#二、比较方式
diff整体策略为:深度优先,同层比较
比较只会在同层级进行, 不会跨层级比较
比较的过程中,循环从两边向中间收拢
当数据发生改变时,订阅者watcher就会调用patch给真实的DOM打补丁
axios是什么
axios 是一个轻量的 HTTP客户端
基于 XMLHttpRequest 服务来执行 HTTP 请求,支持丰富的配置,支持 Promise,支持浏览器端和 Node.js 端。自Vue2.0起,尤大宣布取消对 vue-resource 的官方推荐,转而推荐 axios。现在 axios 已经成为大部分 Vue 开发者的首选
#特性
从浏览器中创建 XMLHttpRequests
从 node.js 创建 http请求
支持 Promise API
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换JSON 数据
客户端支持防御XSRF
#基本使用
安装
// 项目中安装
npm install axios --S
// cdn 引入
导入
import axios from ‘axios’
发送请求
axios({
url:‘xxx’, // 设置请求的地址
method:“GET”, // 设置请求方法
params:{ // get请求使用params进行参数凭借,如果是post请求用data
type: ‘’,
page: 1
}
}).then(res => {
// res为后端返回的数据
console.log(res);
})
并发请求axios.all([])
function getUserAccount() {
return axios.get(‘/user/12345’);
}
function getUserPermissions() {
return axios.get(‘/user/12345/permissions’);
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (res1, res2) {
// res1第一个请求的返回的内容,res2第二个请求返回的内容
// 两个请求都执行完成才会执行
}));
#二、为什么要封装
axios 的 API 很友好,你完全可以很轻松地在项目中直接使用。
不过随着项目规模增大,如果每发起一次HTTP请求,就要把这些比如设置超时时间、设置请求头、根据项目环境判断使用哪个请求地址、错误处理等等操作,都需要写一遍
这种重复劳动不仅浪费时间,而且让代码变得冗余不堪,难以维护。为了提高我们的代码质量,我们应该在项目中二次封装一下 axios 再使用
是什么
Server-Side Rendering 我们称其为SSR,意为服务端渲染
指由服务侧完成页面的 HTML 结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的过程
先来看看Web3个阶段的发展史:
传统服务端渲染SSR
单页面应用SPA
服务端渲染SSR
#传统web开发
网页内容在服务端渲染完成,⼀次性传输到浏览器
打开页面查看源码,浏览器拿到的是全部的dom结构
打开页面查看源码,浏览器拿到的仅有宿主元素#app,并没有内容
#服务端渲染SSR
SSR解决方案,后端渲染出完整的首屏的dom结构返回,前端拿到的内容包括首屏及完整spa结构,应用激活后依然按照spa方式运行
#单页应用SPA
单页应用优秀的用户体验,使其逐渐成为主流,页面内容由JS渲染出来,这种方式称为客户端渲染
Vue SSR是一个在SPA上进行改良的服务端渲染
通过Vue SSR渲染的页面,需要在客户端激活才能实现交互
Vue SSR将包含两部分:服务端渲染的首屏,包含交互的SPA
#二、解决了什么
SSR主要解决了以下两种问题:
seo:搜索引擎优先爬取页面HTML结构,使用ssr时,服务端已经生成了和业务想关联的HTML,有利于seo
首屏呈现渲染:用户无需等待页面所有js加载完成就可以看到页面视图(压力来到了服务器,所以需要权衡哪些用服务端渲染,哪些交给客户端)
但是使用SSR同样存在以下的缺点:
复杂度:整个项目的复杂度
库的支持性,代码兼容
性能问题
跨域是什么
跨域本质是浏览器基于同源策略的一种安全手段
同源策略(Sameoriginpolicy),是一种约定,它是浏览器最核心也最基本的安全功能
所谓同源(即指在同一个域)具有以下三个相同点
协议相同(protocol)
主机相同(host)
端口相同(port)
反之非同源请求,也就是协议、端口、主机其中一项不相同的时候,这时候就会产生跨域
一定要注意跨域是浏览器的限制,你用抓包工具抓取接口数据,是可以看到接口已经把数据返回回来了,只是浏览器的限制,你获取不到数据。用postman请求接口能够请求到数据。这些再次印证了跨域是浏览器的限制。
#二、如何解决
解决跨域的方法有很多,下面列举了三种:
JSONP
CORS
Proxy
利用新的语言特性(es6)
解决架构问题
速度更快
体积减少
更易维护
更接近原生
更易使用
#速度更快
vue3相比vue2
重写了虚拟Dom实现
编译模板的优化
更高效的组件初始化
undate性能提高1.3~2倍
SSR速度提高了2~3倍
体积更小
更易维护
#compositon Api
可与现有的Options API一起使用
灵活的逻辑组合与复用
Vue3模块可以和其他框架搭配使用
更好的Typescript支持
VUE3是基于typescipt编写的,可以享受到自动的类型定义提示
编译器重写
更接近原生
可以自定义渲染 API
更易使用
响应式 Api 暴露出来
ref – 标记dom元素 – 给我当前的组件起小名
$refs : 获取被标记的dom元素 相当于 ref标记的组件本身
1- ref标记 $refs获取
2- event.target
3- directive()
ppt-vuecli-1
|—node_moudule == 项目中安装的依赖模块
|—src == 源码位置 开发目录
|—|—main.js == 打包编译的入口文件
|—|—App.vue == 项目页面入口文件、vue组件
|—|—components == 当前项目的公共子组件目录
|—|—views == 路由组件 – 当前项目的其他组件
|—|—assets == 资源文件夹 一般放一些静态资源
|—|—router == 当前项目的路由文件
|—|—store == 当前项目的状态文件
|— public == 纯静态资源
|—|—index.html == 入口模块文件
|— babel.config.js == babel配置文件
|— gitnore == 用来过滤一些版本控制的文件
|— package.json == 项目文件,记载一些命令和依赖还有简要的项目描述信息
|— README.md == 介绍自己项目 ,可参照github 中star多的项目
|— vue.config.js == vue实例配置文件
2- main.js的作用
main.js是项目的入口文件,项目中所有的页面都会加载main.js,所以main.js,主要有三个作用:
1.实例化Vue。
2.放置项目中经常会用到的插件和CSS样式。例如: 网络请求插件:axios和vue-resource、图片懒加载插件:vue-lazyload
3.存储全局变量。例如(用于的基本信息)
vuex是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享
并以相应的规则保证状态以一种可预测的方式发生变化(响应式的)。Vuex 也集成到 Vue 的官方调试工具 devtools extension (opens new window)
2.vuex优点
1. 能够在 vuex 中集中管理共享的数据,便于开发和后期进行维护
2. 能够高效的实现组件之间的数据共享,提高开发效率
3. 存储在 vuex 中的数据是响应式的,当数据发生改变时,页面中的视图也会同步更新
4.vuex中的数据操作可以在开发阶段通过开发调试工具来进行追踪,便于开发
简单来说,vuex 就是为了实现组件间通信的。使用 vuex 的好处:可以跨层级进行通信;vuex 中的所有操作都有记录;vuex 独立于组件系统,是专门用来管理数据的框架。
1 State:存放data数据的对象 管理数据状态 或者 数据源
3.getters: 存放多个计算属性的对象
4. actions:// 包含多个异步操作的方法 或者 间接修改 state状态方法的对象
1、任何一个 Vue Component 都有一个与之对应的 Watcher 实例
2、Vue 的 data 上的属性会被添加 getter 和 setter 属性
3、当 Vue Component render 函数被执行的时候, data 上会被 触碰(touch), 即被读, getter 方法会被调用, 此时 Vue 会去记录此 Vue component 所依赖的所有 data。(这一过程被称为依赖收集)
4、data 被改动时(主要是用户操作), 即被写, setter 方法会被调用, 此时 Vue 会去通知所有依赖于此 data 的组件去调用他们的 render 函数进行更新
库 :jquery、zepto — 提供项目常用的方法、相当于工具包
组件:bootstrap、swiper — 多个插件的集合体,提供js 结构 样式 可以快速构建页面
插件:iScroll — 把项目中某一个功能进行封装
框架:angular(MVC)、vue(MVVM)、react、uni-app — 库+组件的集合体
1- computed:计算属性
1- 自身需要依赖另一个值得改变而使当前所在DOM更新
2- 计算属性不可以与data中的数据重名
3- 计算属性的方法不需要加括号调用,方法需要单独加括号调用 因为 计算属性 不属于方法 属于属性
4- 计算属性具有缓存机制
当计算属性第一次获取到响应式数据时,会缓存,在后期渲染视图时,会观察响应式数据是否改变,如果改变会调用计算属性,如果没有改变会读取存储的数据,方法只用更新就会重新调用
5- 当获取计算属性时会触发getter ,当设置修改计算机属性是会触发setter
注意:计算属性不可以使用箭头函数,否则this不会指向这个组件的实例
2- watch:监听属性
1- 当检测的值发生改变时,那么对应的方法会自动执行
2- deep 开启深度监视
发现对象内部值得变化,可以在选项参数中指定deep:true 作为深度监视,但是监听数组的变更则不需要使用
3- immediate
在选项参数中指定immediate:true将立即以表达式的当前值触发回调
computed有缓存,watch没有缓存
computed不支持异步,watch支持异步
computed需要返回值,watch不需要返回值
computed的属性名不用在data中定义,watch需要在data中定义
全局前置守卫:beforeEach
全局解析守卫:beforeResolve
全局后置钩子:afterEach
路由独享守卫:beforeEnter
组件内—进入:beforeRouteEnter
组件内—更新:beforeRouteUpdate
组件内—离开:beforeRouteLeave
里面的三个参数:
to : 即将要进入的目标 路由对象
from : 当前导航正要离开的路由
next() 通过调用 next 方法 才会进入到目标路由对象
Next()默认参数为:
True:允许跳转,
False: 拒绝跳转,
路由路径: 跳转到该路径
函数:在跳转前进行逻辑处理,从而决定是否跳转。
函数内的参数
$route:获取路由信息 指当前路由实例跳转到的路由对象
包括:
$route.path 字符串,等于当前路由对象的路径,会被解析为绝对路径,如/home/ews
$route.name 当前路由的名字,如果没有使用具体路径,则名字为空
$route.router 路由规则所属的路由器
$route.matchd 数组,包含当前匹配的路径中所包含的所有片段所对象的配置参数对
象
$route.query 对象,包含路由中查询参数的键值对。会拼接到路由 url 后面
$route.params 对象,含路有种的动态片段和全匹配片段的键值对,不会拼接到路由
的 url 后面
r o u t e r :获取路由整个实例指整个路由实例,可操控整个路由通过‘ router:获取路由整个实例 指整个路由实例,可操控整个路由 通过‘ router:获取路由整个实例指整个路由实例,可操控整个路由通过‘router.push’往其中添加任意的路由对象 钩子函数等
1、query 传参配置的是 path,而 params 传参配置的是 name,在 params 中配置 path 无效
2、query 在路由配置不需要设置参数,而 params 必须设置
3、query 传递的参数会显示在地址栏中
4、params 传参刷新会无效,但是 query 会保存传递过来的值,刷新不变 ;
5、接收参数使用 this.$router 后面就是搭配路由的名称就能获取到参数的值
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效。
Vue Router 支持开箱即用的动态导入,这意味着你可以用动态导入代替静态导入:
// 将
// import UserDetails from ‘./views/UserDetails.vue’
// 替换成
const UserDetails = () => import(‘./views/UserDetails.vue’)
const router = createRouter({
routes: [{ path: ‘/users/:id’, component: UserDetails }],
})
Vue中路由模式有两种:hash模式和history模式。hash模式中,URL的hash值(即#后面的内容)变化时,不会向服务器发送请求,而是通过hashchange事件来监听URL的变化,从而改变页面的显示内容。而history模式中,URL的变化会向服务器发送请求,可以在服务器端进行URL的匹配和响应。
1、双向数据绑定原理不同
vue2:vue2的双向数据绑定是利用ES5的一个API:Object.definePropert() 对数据进行劫持,结合发布订阅模式的方式来实现的。
vue3:vue3中使用了ES6的Proxy API对数据代理。相比vue2.x,使用proxy的优势如下:
defineProperty只能监听某个属性,不能对全对象监听
可以省去for in,闭包等内容来提升效率(直接绑定整个对象即可)
可以监听数组,不用再去单独的对数组做特异性操作vue3.x可以检测到数组内部数据的变化。
2、是否支持碎片
vue2:vue2不支持碎片。
vue3:vue3支持碎片(Fragments),就是说可以拥有多个根节点。
3、API类型不同
vue2:vue2使用选项类型api,选项型api在代码里分割了不同的属性:data,computed,methods等。
vue3:vue3使用组合式api,新的合成型api能让我们使用方法来分割,相比于旧的api使用属性来分组,这样代码会更加简便和整洁。
4、定义数据变量和方法不同
vue2:vue2是把数据放入data中,在vue2中定义数据变量是data(){},创建的方法要在methods:{}中。
vue3:,vue3就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。使用以下三个步骤来建立反应性数据:
从vue引入reactive;
使用reactive() 方法来声明数据为响应性数据;
使用setup()方法来返回我们的响应性数据,从而template可以获取这些响应性数据。
5、生命周期钩子函数不同
vue2:vue2中的生命周期:
beforeCreate 组件创建之前
created 组件创建之后
beforeMount 组价挂载到页面之前执行
mounted 组件挂载到页面之后执行
beforeUpdate 组件更新之前
updated 组件更新之后
vue3:vue3中的生命周期:
setup 开始创建组件前
onBeforeMount 组价挂载到页面之前执行
onMounted 组件挂载到页面之后执行
onBeforeUpdate 组件更新之前
onUpdated 组件更新之后
而且vue3.x 生命周期在调用前需要先进行引入。除了这些钩子函数外,vue3.x还增加了onRenderTracked 和onRenderTriggered函数。
6、父子传参不同
vue2:父传子,用props,子传父用事件 Emitting Events。在vue2中,会调用this$emit然后传入事件名和对象。
vue3:父传子,用props,子传父用事件 Emitting Events。在vue3中的setup()中的第二个参数content对象中就有emit,那么我们只要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。
7、指令与插槽不同
vue2:vue2中使用slot可以直接使用slot;v-for与v-if在vue2中优先级高的是v-for指令,而且不建议一起使用。
vue3:vue3中必须使用v-slot的形式;vue3中v-for与v-if,只会把当前v-if当做v-for中的一个判断语句,不会相互冲突;vue3中移除keyCode作为v-on的修饰符,当然也不支持config.keyCodes;vue3中移除v-on.native修饰符;vue3中移除过滤器filter。
8、main.js文件不同
vue2:vue2中我们可以使用pototype(原型)的形式去进行操作,引入的是构造函数。
vue3:vue3中需要使用结构的形式进行操作,引入的是工厂函数;vue3中app组件中可以没有根标签。
关键词:
组合式api;proxy;支持碎片;组合式api;composition;生命周期;
与 watchEffect() 相比,watch() 使我们可以:
懒执行副作用:watch是懒侦听执行的;watchEffect是首次就会执行
触发侦听器的来源:watch是明确知道由哪个依赖引起的侦听,watchEffect不明确
可以访问所侦听状态的前一个值和当前值:watch可以,watchEffect不可以。
关键词:
懒侦听、当前值、前一个值,新值,旧值
setup是什么,作用
1、新的选项,所有的组合api函数都在此使用,只在初始化时执行一次
2、函数如果返回对象,对象中的属性与方法,在模板中可以直接使用
执行时机:
1、在beforeCreate之前执行一次,此时组件对象还没有创建
2、This的值为undefined,不能通过this操作 data、computed、methods、props
3、所有的composition api 都不能使用this
返回值:
1、一般都返回一个对象,用于向模板返回数据,返回的数据模板可以直接使用
2、返回的对象的属性与data返回的数据 在组件对象中属性合并
3、返回的对象的方法与methods返回的数据 在组件对象中方法合并
4、切记:
(1)如遇相同名字 setup优先
(2)Methods可以访问setup中属性与方法,setup不可以访问data与methods ,此方式不推荐使用
(3)Setup不能是一个异步函数,如果设置为异步函数返回的是一个promise,模板不能获取到return返回的对象
参数:setup(props, context) / setup(props, {attrs, slots, emit})
props:接收组件的属性,
context:上下文对象,包括 slots,attrs,emit,expose
(1)attrs: 包含没有在props配置中声明的属性的对象, 相当于 this.$attrs
(2)slots: 包含所有传入的插槽内容的对象, 相当于 this.$slots
(3)emit: 用来分发自定义事件的函数, 相当于 this.$emit
beforeCreate 和 created 已经合并成一个新的函数 setup。
deactivated 和 activated 已经被废弃,取而代之的是 beforeMount 和 beforeUpdate。因为在Vue3中,keep-alive组件被完全重写了,其默认行为现在与没有keep-alive一样。
1、Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:
beforeDestroy改名为 beforeUnmount
destroyed改名为 unmounted
2、Vue3.0也提供了 Composition API 形式的生命周期钩子,Option API形式的钩子对应关系如下:
beforeCreate===>setup()
created=======>setup()
beforeMount ===>onBeforeMount
mounted=======>onMounted
beforeUpdate===>onBeforeUpdate
updated =======>onUpdated
beforeUnmount ==>onBeforeUnmount
unmounted =====>onUnmounted
关键词:
beforeUnmount;unmounted;onBeforeMount;onMounted;onBeforeUpdate;onUpdated;onBeforeUnmount;onUnmounted
Vue 3.x中的生命周期函数相比Vue 2.x发生了一些变化:
beforeCreate 和 created 已经合并成一个新的函数 setup。
deactivated 和 activated 已经被废弃,取而代之的是 beforeMount 和 beforeUpdate。因为在Vue3中,keep-alive组件被完全重写了,其默认行为现在与没有keep-alive一样。
1、vue2.x的响应式
实现原理:
对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。
数组类型:通过重写更新数组的一系列方法(如:push,pop等)来实现拦截。(对数组的变更方法进行了包裹)。
存在问题:
新增属性、删除属性, 界面不会更新。
直接通过下标修改数组, 界面不会自动更新。
Vue3.0的响应式
实现原理:
通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
通过Reflect(反射): 对源对象的属性进行操作。
十四、vue3响应式数据的判断
答案:
isRef: 检查一个值是否为一个 ref 对象
isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理
关键词:
isRef;isReactive;isReadonly;isProxy;
定义数据角度:
ref用来定义:基本类型数据。
reactive用来定义:对象(或数组)类型数据。
备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过reactive转为代理对象。
原理角度:
ref通过Object.defineProperty()的get与set来实现响应式(数据劫持)。
reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
使用角度:
ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。
reactive定义的数据:操作数据与读取数据:均不需要.value。
vue3性能比vue2快,
体积比vue2小
支持组合式API
提供了更先进的组件
暴露了自定义渲染的api
pinia是Vue3中的状态管理库,具有以下核心属性:
$state:一个ref对象,用于存储状态数据。
$getters:一个包含所有状态的getter函数的对象。
$actions:一个包含所有操作状态的action函数的对象。
在组件中使用pinia,需要通过useStore方法来获取一个与组件相关联的状态管理对象。
React,用于构建用户界面的 JavaScript 库,只提供了 UI 层面的解决方案
遵循组件设计模式、声明式编程范式和函数式编程概念,以使前端应用程序更高效
使用虚拟 DOM 来有效地操作 DOM,遵循从高阶组件到低阶组件的单向数据流
帮助我们将界面成了各个独立的小块,每一个块就是组件,这些组件之间可以组合、嵌套,构成整体页面
react 类组件使用一个名为 render() 的方法或者函数组件return,接收输入的数据并返回需要展示的内容
特性
React 特性有很多,如:
JSX 语法
单向数据绑定
虚拟 DOM
声明式编程
Component
着重介绍下声明式编程及 Component
优势
通过上面的初步了解,可以感受到 React 存在的优势:
高效灵活
声明式的设计,简单使用
组件式开发,提高代码复用率
单向响应的数据流会比双向绑定的更安全,速度更快
1- 初始化阶段:ReactDOM.render() 开始了第一次渲染
constructor 数据的初始化。【避免将 props 的值复制给 state!这是一个常见的错误:】
componentWillMount 在挂载之前也就是render之前被调用
getDerivedStateFromProps 从props获取state
render class组件中唯一必须实现的方法。
componentDidMount 在组件挂在后(插入到dom树中)后立即调用
2- 更新阶段:props state 组件内部 this.setState() 或者是父组件重新渲染
componentWillReceiveProps () 在已挂载的组件接收新的props之前调用。
shouldComponentUpdate 在渲染之前被调用,默认返回为true。
componentWillUpdate 当组件接收到新的props和state会在渲染前调用,初始渲染不会调用该方法
getSnapshotBeforeUpdate 在最后一次渲染(提交到dom节点)之前调用,替换componetnWillUpdate
componentDidUpdate 在更新之后立即调用,首次渲染不会调用,之后每次重新渲染都会被调用。
3- 销毁:触发销毁的方法
componentWillUnmount() 在组件卸载和销毁之前调用
函数组件:首字母大写,需要return出react元素
类组件:首字母大写,需要使用render方法,return出react元素
区别:
函数组件是无状态组件的思想
函数组件中不能用State,不能用组件的生命周期方法,这就决定了函数组件都是展开性组件,接收props,渲染DOM,而不关注其它逻辑
函数组件中没有this
函数组件更容易理解。当你看到一个函数组件时,你就知道它的功能只是接收属性,渲染页面,它不执行与UI无关的逻辑处理,它只是一个纯函数
Hook 是一个特殊的参数,它是 React 16.8 中新增的特性,可以让你在不编写 class 的情况下使用 State 以及其他的 React 特性。 解决了什么问题:通过自定义hook能够更好的封装我们的功能,hooks使函数组件的使用得到了扩充,拥有了类组件相似的功能,使用hook能够解 决大多数问题,并且还拥有代码的复用机制。useEffect 首次执行
结果的可预测性 - 由于总是存在一个真实来源,即 store ,因此不存在如何将当前状态与动作和应用的其他部分同步的问题。
可维护性 - 代码变得更容易维护,具有可预测的结果和严格的结构。
服务器端渲染 - 你只需将服务器上创建的 store 传到客户端即可。这对初始渲染非常有用,并且可以优化应用性能,从而提供更好的用户体验。
开发人员工具 - 从操作到状 态更改,开发人员可以实时跟踪应用中发生的所有事情。
社区和生态系统 - Redux 背后有一个巨大的社区,这使得它更加迷人。一个由才华横溢的人组成的大型社区为库的改进做出了贡献,并开发了各种应用。
易于测试 - Redux 的代码主要是小巧、纯粹和独立的功能。这使代码可测试且独立。
组织 - Redux 准确地说明了代码的组织方式,这使得代码在团队使用时更加一致和简单
react的优缺点
优点:
提高了应用性能和开发效率
使用JSX,代码可读性好
react的componentWillUnmount生命周期,能够清除相关所有事件,避免内存泄露
并不直接对DOM进行操作,引入了一个虚拟DOM的概念,安插在js和真实DOM中间,性能好,速度快
缺点:
每次 state 更改,render 函数都要生成完整的虚拟 DOM. 哪怕 state 改动很小,render函数也会完整计算一遍。如果 render 函数很复杂,这个过程就白白浪费了很多计算资源
React 路由是一个构建在 React 之上的强大的路由库,它有助于向应用程序添加新的屏幕和流。这使 URL 与网页上显示的数据保持同步。它负责维护标准化的结构和行为,并用于开发单页 Web 应用。 React 路由有一个简单的API
react组件有哪些
withRouter 组件 如果一个组件不是路由绑定组件,那么该组件的 props 中是没有路由相关对象的,虽然我们可以通过传参的方式传入,但是如果结构复杂,这样做会特别的繁琐。幸好,我们可以通过 withRouter 方法来注入路由对象.
Redirect 组件
Switch 组件该组件只会渲染首个被匹配的组件.
包在 Switch 组件中的 Route 会一项一项的匹配, 匹配成功一项之后,就不会再继续匹配其它内容了.
NavLink 组件
Link 组件
Route 组件
Navigate 重定
Routes
JSX 是 React 中用于描述用户界面的一种语法扩展,它允许在 JavaScript 代码中编写类似 HTML 的标记,使得组件的结构和逻辑更加清晰和易于维护。
JSX 的特性包括:
JSX 允许在 JavaScript 中直接嵌入 HTML 标签;
JSX 标记可以包含任意的 JavaScript 表达式,使用花括号 {} 进行包裹;
JSX 中的标记可以自定义属性,包括样式、事件处理等;
JSX 本质上是 JavaScript,因此可以在 JSX 中使用 JavaScript 的所有特性和语法。
JSX 的优点在于它能够让开发者更加自然地描述用户界面,同时提供了更好的可读性和可维护性,使得代码更加易于理解和扩展。
JSX是react的语法糖,它允许在html中写JS,它不能被浏览器直接识别,需要通过webpack、babel之类的编译工具转换为JS执行
JSX与JS的区别:
JS可以被打包工具直接编译,不需要额外转换,jsx需要通过babel编译,它是React.createElement的语法糖,使用jsx等价于React.createElement
jsx是js的语法扩展,允许在html中写JS;JS是原生写法,需要通过script标签引入
————————————————
版权声明:本文为CSDN博主「weixin_42023243」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42023243/article/details/129727272
相似之处:
用于创建UI的js库
使用起来轻快便捷
都用了虚拟DOM
都是基于组件的架构
不同点 :
vue使用的html模板;react使用的是js
vue有双向绑定语法
vue增加了语法糖computed和watch等,react需要自己写逻辑来实现
react用了jsx语法
react整体思路是编程式,推荐组件化,数据不变,单向数据流;vue数据可变,双向绑定,声明式的写法
在React中,状态管理需要使用Redux。Redux是一个可预测的状态容器,它让你更方便地管理整个应用的状态。
下面是Redux的关键代码和工作流程:
关键代码:
1.创建store:
import { createStore } from ‘redux’;
const initialState = {
counter: 0
};
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case ‘INCREMENT’:
return {
…state,
counter: state.counter + 1
};
case ‘DECREMENT’:
return {
…state,
counter: state.counter - 1
};
default:
return state;
}
};
const store = createStore(counterReducer);
2.在组件中使用store:
import { useDispatch, useSelector } from ‘react-redux’;
A
const Counter = () => {
const counter = useSelector(state => state.counter);
const dispatch = useDispatch();
const handleIncrement = () => {
dispatch({ type: ‘INCREMENT’ });
};
const handleDecrement = () => {
dispatch({ type: ‘DECREMENT’ });
};
return (
{counter}
);
};
工作流程:
创建store:在Redux中,应用的状态被存储在一个单一的JavaScript对象中,这个对象被称为store。store是通过调用Redux中的createStore函数创建的。在createStore函数中,需要传入一个reducer,这个reducer用来描述应用的状态变化。;
定义reducer:reducer是一个纯函数,它接受旧的state和一个action,并返回新的state。reducer描述了应用状态的变化。
创建action:在Redux中,要改变应用的状态,需要发出一个action。action是一个包含type属性的普通JavaScript对象。type属性描述了要发生的变化。
分发action:要分发一个action,需要调用store的dispatch方法,并传入action。store将action传递给reducer,并使用reducer返回的新state更新应用的状态。
更新组件:在React中,可以使用react-redux库的useSelector和useDispatch钩子来更新组件。useSelector用来选择state中的一部分数据,useDispatch用来分发action。当状态改变时,React会重新渲染组件。
父子组件通信:可以通过props属性将父组件的数据传递给子组件,从而实现父子组件之间的通信。
子父组件通信:子组件可以通过回调函数将自己的数据传递给父组件,从而实现子父组件之间的通信。
兄弟组件通信:可以通过共同的父组件来传递数据,或者使用React中的Context API进行跨级传递数据。
非父子组件通信:可以使用全局事件总线、Redux等状态管理库,或者使用React中的Context API进行全局数据共享。
状态(state)和属性(props)是React组件中两种不同的数据传递方式。state是组件内部自身的状态,可以通过setState方法进行更新,同时也可以通过props从父组件传递数据到子组件中。props则是组件外部传递给组件的数据,组件内部无法通过setState方法修改props中的值。
第1种 state
{item.title}
console.log(props.location.state.gid)
第二种params
路由跳转
{item.title}
路由展示
console.log(props.match.params.gid)
类组件
标记 ref={this.inp}
inp=React.createRef()
函数组件
ref={inp}
inp=useRef()