热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

redux以及reactredux简单实现

写在前头redux简介 随着JavaScript单页应用开发日趋复杂,JavaScript需要管理比任何时候都要多的state(状态)。这些state可能包括服务器响应、缓存数据、

写在前头

redux 简介

  随着 Javascript 单页应用开发日趋复杂,Javascript 需要管理比任何时候都要多的 state (状态)。 这些 state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。

  管理不断变化的 state 非常困难。如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依次地,可能会引起另一个 view 的变化。直至你搞不清楚到底发生了什么。state 在什么时候,由于什么原因,如何变化已然不受控制。 当系统变得错综复杂的时候,想重现问题或者添加新功能就会变得举步维艰。

  如果这还不够糟糕,考虑一些来自前端开发领域的新需求,如更新调优、服务端渲染、路由跳转前请求数据等等。前端开发者正在经受前所未有的复杂性,难道就这么放弃了吗?当然不是。

  这里的复杂性很大程度上来自于:我们总是将两个难以理清的概念混淆在一起:变化和异步。 如果把二者分开,能做的很好,但混到一起,就变得一团糟。一些库如 React 试图在视图层禁止异步和直接操作 DOM 来解决这个问题。美中不足的是,React 依旧把处理 state 中数据的问题留给了我们自己。而 redux 就可以来帮我管理这些状态;

demo 演示

《redux以及react-redux简单实现》

demo 结构树

├── config-overrides.js
├── .gitignore
├── package.json
├── package-lock.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── README.md
└── src
├── App.js
├── Demo
│   ├── actionCreate.js
│   ├── Demo.jsx
│   ├── react-redux.js
│   ├── reducer.js
│   ├── redux.js
│   ├── style.css
│   └── thunk.js
└── index.js

一、 redux API createStore 的实现

  首先我们先结合 reducer 以及 action 的知识简单实现开头展示的 demo, 并逐步揭晓 createStore 的神秘面纱;

1.1 准备工作:

创建 reducer 并导出 reducer

// reducer.js
const initState = { user: 'qianyin', age: 18, sex: '男' };
export const reducer = (state=initState, action) => {
switch(action.type){
case 'USER_UPDATE':
return {...state, ...action.payload};
case 'AGE_GROW':
return {...state, age: state.age + 1};
case 'SEX_UPDATE':
return {...state, ...action.payload};
default:
return state;
}
}

创建 action 创建函数

// actionCreate.js
export const changeUser = (user) => {
return {
payload:{user},
type: 'USER_UPDATE',
};
}
export const changeAge = () => {
return { type: 'AGE_GROW' };
}

通过 react 在页面上预先绘制出基本的元素

/* style.css */
.btn{
height: 31px;
}
.input{
height: 25px;
}

// Demo.jsx
import React from 'react';
import './style.css';
export default class Demo extends React.Component{
OnChange= () => {}
OnClick= () => {}
render(){
return (


user: xxx, age: xxx


user:

 


);
}
}

最终页面将渲染如下:

《redux以及react-redux简单实现》

1.2 demo 的初次实现代码
  • 创建全局状态 state;
  • 创建监听队列;
  • 针对监听队列,新增函数用于将指定监听对象添加到队列中;
  • 在函数 dispatch 中执行 reducer 将返回值作为新的 state, 同时依次执行监听对象;
  • 默认执行一次 dispatch 给定一个 type 相对唯一的 action, 目的是为了匹配 reducer 的默认状态值,从而实现对 redux state 的初始化;
  • 在组件 Demo 通过在函数 update 使用 this.setState 将全局 state 保存到 react state 中,并将函数 update 添加到监听队列中;从而使得当我们一旦试图通过 dispatch 修改全局状态时,能够及时更新 react state 最终触发 react 生命周期 render;
  • 在 react 生命周期 componentDidMount 中我们除了将 update 添加到监听队列以外,还需手动执行一次 update 其主要目的就是为了首次初始化 react state;

// Demo.jsx
import React from 'react';
import { changeAge, changeUser } from './actionCreate';
import { reducer } from './reducer';
import './style.css';
let state;
const listeners = [];
const subscribe = (listener) => {
listeners.push(listener);
}
const dispatch = (action) => {
state = reducer(state, action);
console.log(state);
listeners.forEach(v => v());
}
dispatch({type: '%$&HJKAJJHDJHJ'});
export default class Demo extends React.Component{
state = {user: 'xxx', age: 'xxx'};
componentDidMount(){
subscribe(this.update);
this.update();
}
update = () => {
this.setState(state);
}
OnChange= (e) => {
dispatch(changeUser(e.target.value));
}
OnClick= () => {
dispatch(changeAge());
}
render(){
return (


user: {this.state.user}, age: {this.state.age}


user:

 


);
}
}
1.3 API createStore 的实现

  其实上文的代码中对于 createStore 的实现原理已经基本描述清除,下面我们只是单纯的对代码进行了简单的封装;当然为了能够获取到 state 我们专门增加了一个函数 getState 来实现它;

createStore 函数实现

// redux.js
export const createStore = (reducer) => {
// 声明常量
let state;
const listeners = [];
// 获取状态
const getState = () => {
return state;
}
// 添加监听对象
const subscribe = (listener) => {
listeners.push(listener);
}
// [1]执行reducer修改状态 [2]遍历执行监听对象
const dispatch = (action) => {
state = reducer(state, action);
listeners.forEach(v => v());
}
// 初始化 state
dispatch({type: '%$&HJKAJJHDJHJ'}); // 暴露接口
return {getState, subscribe, dispatch};
}

调用 createStore 并对 demo 进行修改

// Demo.jsx
import React from 'react';
import './style.css';
import { changeAge, changeUser } from './actionCreate';
import { reducer } from './reducer';
import { createStore } from './redux';
const store = createStore(reducer);
export default class Demo extends React.Component{
state = {user: 'xxx', age: 'xxx'};
componentDidMount(){
store.subscribe(this.update);
this.update();
}
update = () => {
this.setState(store.getState());
}
OnChange= (e) => {
store.dispatch(changeUser(e.target.value));
}
OnClick= () => {
store.dispatch(changeAge());
}
render(){
return (


user: {this.state.user}, age: {this.state.age}


user:

 


);
}
}

二、 react-redux API Provider 的实现

  在 react 中大多数情况下我们需要将状态传递给后代组件进行使用的,当然通过 props 是可以实现状态从父级到子级的传递,但是当状态需要传递的层级比较深的情况下再使用 props 就显得无力了,那么在 react-redux 中它是如何实现对 store 的传递的呢?

2.1 react context 的引入

在 App.js 中创建 store 并通过 context 传递 store

// App.js
import React, { Component } from 'react';
import propTypes from 'prop-types';
import { createStore } from './Demo/redux';
import { reducer } from './Demo/reducer';
import Demo from './Demo/Demo';
// 创建 store
const store = createStore(reducer);
class App extends Component {
// 声明 childContextTypes 状态属性类型
static childCOntextTypes= {
store: propTypes.object
};
// 设置 childContext
getChildContext(){
return {store}
}
render() {
return ;
}
}
export default App;

在子组件 Demo 中通过 context 获取 store 并对代码进行简单修改

// Demo.jsx
import React from 'react';
import propTypes from 'prop-types';
import './style.css';
import { changeAge, changeUser } from './actionCreate';
export default class Demo extends React.Component{
// 设置 context 状态值类型
static cOntextTypes= {
store: propTypes.object
};
constructor(props, context){
super(props, context);
// 获取store
this.store = context.store;
this.state = {user: 'xxx', age: 'xxx'};
}
componentDidMount(){
this.store.subscribe(this.update);
this.update();
}
update = () => {
this.setState(this.store.getState());
}
OnChange= (e) => {
this.store.dispatch(changeUser(e.target.value));
}
OnClick= () => {
this.store.dispatch(changeAge());
}
render(){
return (


user: {this.state.user}, age: {this.state.age}


user:

 


);
}
}
2.2 封装代码实现 Provider

  通过 react context 我们实现了对 store 的传递,到这里 Provider 的功能以及实现原理基本上应该算是清晰了,无非就是对组件进行包裹同时通过 react context 来传递共享 store;那么接下来我们通过对代码的封装来实现 Provider 组件;

Provider 组件:实现对 store 的传递

// react-redux.js
import React from 'react';
import propTypes from 'prop-types';
export class Provider extends React.Component{
// 设置 childContext 状态值类型
static childCOntextTypes= {
store: propTypes.object
};
// 设置 childContext
getChildContext(){
return {store: this.props.store}
}
render(){
return this.props.children;
}
}

重写 App.js: 对 Provider 组件的调用

// App.js
import React, { Component } from 'react';
import { createStore } from './Demo/redux';
import { Provider } from './Demo/react-redux';
import { reducer } from './Demo/reducer';
import Demo from './Demo/Demo';
// 创建 store
const store = createStore(reducer);
class App extends Component {
render() {
// 调用接口 Provider
return ;
}
}
export default App;

三、 react-redux API connect 高阶组件的实现

  上文中在后代组件如果需要获取 store 则需要手动通过获取 react context 来调用 store 并且需要显性的调用 store 内部的方法来进行一些操作;接下来我们来实现这么一个高阶组件 connect,我们只需要提供所需的 redux state 以及 action 创建函数,即可通过 props 获取到相应的 redux state , 并且允许直接通过 props 调用action 创建函数来试图修改 redux state ;

创建高阶组件 connect

// react-redux.js
export const cOnnect= (mapStateToProps, mapDispatchToProps) => (Component) => {
return class NewComponent extends React.Component{
render(){
return
}
}
}

获取store

// react-redux.js
export const cOnnect= (mapStateToProps, mapDispatchToProps) => (Component) => {
return class NewComponent extends React.Component{
// 设置 context 状态值类型
static cOntextType= {
store: propTypes.object
};
// [1]获取 store [2]设置空 react state
constructor(props, context){
super(props, context);
this.store = context.store;
this.state = {};
}
render(){
return
}
}
}

添加监听对象,并尝试通过 props 将状态传递给子组件

export const cOnnect= (mapStateToProps, mapDispatchToProps) => (Component) => {
return class NewComponent extends React.Component{
static cOntextType= {
store: propTypes.object
};
constructor(props, context){
super(props, context);
this.store = context.store;
this.state = {};
}
// [1]添加监听对象 [2]手动执行监听对象,初始化 react state
componentDidMount(){
this.store.subscribe(this.update);
this.update();
}
update = () => {
// 获取全部redux state 并添加到 react state
const state = this.store.getState();
this.setState(state);
}
render(){
// 通过 props 将 react state 全部传给子组件
return
}
}
}

通过 mapStateToProps 获取指定 redux state

// react-redux.js
export const cOnnect= (mapStateToProps, mapDispatchToProps) => (Component) => {
return class NewComponent extends React.Component{
static cOntextType= {
store: propTypes.object
};
constructor(props, context){
super(props, context);
this.store = context.store;
this.state = {};
}
componentDidMount(){
this.store.subscribe(this.update);
this.update();
}
update = () => {
// 执行 mapStateToProps 只获取用户指定需求的 state
const state = this.store.getState();
const filterState = mapStateToProps(state);
this.setState(filterState);
}
render(){
return
}
}
}

通过 mapDispatchToProps 获取 action 创建函数: 使用 dispatch 包裹后返回

// react-redux.js
// react-redux.js
export const cOnnect= (mapStateToProps, mapDispatchToProps) => (Component) => {
return class NewComponent extends React.Component{
static cOntextTypes= {
store: propTypes.object
};
constructor(props, context){
super(props, context);
this.store = context.store;
this.state = {};
}
componentDidMount(){
this.store.subscribe(this.update);
this.update();
}
update = () => {
// 处理 state ===> 获取用户指定的 state
const state = this.store.getState();
const filterState = mapStateToProps(state);
// 使用 dispatch 对 mapDispatchToProps 中的 action 创建函数进行包裹后返回
const actiOnFun= {};
for(let key in mapDispatchToProps){
actionFun[key] = (...args) => {
this.store.dispatch(mapDispatchToProps[key](...args));
}
}
// 一种简写方式: 骚操作
// const actiOnFun= Object.keys(mapDispatchToProps)
// .reduce((total, item) => {
// return { ...total, [item]: (...args) => {dispatch(mapDispatchToProps[item](...args));}
// } } ,{});
this.setState({...filterState, ...actionFun});
}
render(){
return
}
}
}

调用高阶组件:修改 Demo.jsx

// Demo.jsx
import React from 'react';
import { changeAge, changeUser } from './actionCreate';
import { connect } from './react-redux';
import './style.css';
// 编写 mapStateToProps 参数 redux state 返回所需的 redux state
const mapStateToProps = (state) => {
return {user: state.user, age: state.age};
}
// 调用高阶组件
@connect(mapStateToProps, {changeAge, changeUser})
export default class Demo extends React.Component{
OnChange= (e) => {
this.props.changeUser(e.target.value);
}
OnClick= () => {
this.props.changeAge();
}
render(){
return (


user: {this.props.user}, age: {this.props.age}


user:

 


);
}
}

四、redux API bindactioncreators 的实现

  在上文我们对 mapDispatchToProps 的处理过程就是 API bindactioncreators 的功能: 将给定 action 创建函数使用 dispatch 进行包裹后返回;

封装 bindactioncreators

// redux.js
export const bindactiOncreators= (mapDispatchToProps, dispatch) => {
const actiOnFun= {};
// 遍历 mapDispatchToProps 中每个 action 创建函数 并使用 dispatch 包裹后返回
for(let key in mapDispatchToProps){
actionFun[key] = (...args) => {
dispatch(mapDispatchToProps[key](...args));
}
}
return actionFun;
// 一种简写方式: 骚操作
// return actiOnFun= Object.keys(mapDispatchToProps)
// .reduce((total, item) => {
// return { ...total, [item]: (...args) => {dispatch(mapDispatchToProps[item](...args));}
// } } ,{});
}

修改 connect :

// react-redux.js
import { bindactioncreators } from './redux';
....
export const cOnnect= (mapStateToProps, mapDispatchToProps) => (Component) => {
return class NewComponent extends React.Component{
static cOntextTypes= {
store: propTypes.object
};
constructor(props, context){
super(props, context);
this.store = context.store;
this.state = {};
}
componentDidMount(){
this.store.subscribe(this.update);
this.update();
}
update = () => {
const state = this.store.getState();
const filterState = mapStateToProps(state);
// 调用 API bindactioncreators
// 对 mapDispatchToProps 内每个 action 创建函数使用 dispatch 进行包裹后返回
const actiOnFun= bindactioncreators(mapDispatchToProps, this.store.dispatch);
this.setState({...filterState, ...actionFun});
}
render(){
return
}
}
}

五、redux API applyMiddleware 的实现

  到此简化版的 react-redux 算是已经初步完成,但是假如我们想要我们的 age 值的增长是一个异步操作,比如:通过按钮点击后经过两秒再修改 age ,而不是一点击按钮就立即修改值;这样我们又该怎么实现呢?
  当然我们可以通过 setTimeout 两秒后再执行 action 创建函数,比如这样:

OnClick= () => {
setTimeout(()=>{
// 两秒后执行 action 创建函数
this.props.changeAge();
}, 2000);
}

  但是呢事实上我们并不愿意像上面那么整,我们想要这么一种效果:我们只需要简单的调用 action 创建函数即可实现异步操作,而不是需要进行额外的操作;这时我们就需要为我们的 react-redux 编写一个中间件来实现这么一个效果;

5.1 准备工作

新增action 创建函数

  在这之前我们所有的 acton 创建函数都是直接返回一个 action 对象,下面我们写一个不一样的 action 创建函数, 它返回的不再是一个 action 对象而是一个函数,并且该函数接收两个参数 dispatch 以及 getState, 在该函数内部我们进行相应的异步操作,比如:修改 age 值;

// actionCreate.js
export const asyncChangeAge = () => {
// 返回函数
return (dispatch, getState) => {
setTimeout(v=>{
console.log('==>', getState());
dispatch({type: 'AGE_GROW'});
}, 1000);
}
}

修改页面:新增按钮并绑定点击事件,并且调用 asyncChangeAge 函数;

// Demo.jsx
// Demo.jsx
import React from 'react';
import './style.css';
// 导入 asyncChangeAge
import { changeAge, changeUser, asyncChangeAge } from './actionCreate';
import { connect } from './react-redux';
const mapStateToProps = (state) => {
return {user: state.user, age: state.age};
}
// 添加 asyncChangeAge
@connect(mapStateToProps, {changeAge, changeUser, asyncChangeAge})
export default class Demo extends React.Component{
OnChange= (e) => {
this.props.changeUser(e.target.value);
}
OnClick= () => {
this.props.changeAge();
}
// 点击事件
OnClickAsync= () => {
this.props.asyncChangeAge();
}
render(){
return (


user: {this.props.user}, age: {this.props.age}


user:

 

{/* 新增按钮 */}


);
}
}

页面的变化其实很简单就是新增了一个按钮:

《redux以及react-redux简单实现》

5.2 需求实现

  接下来我们先什么都不考虑先来实现我们的需求,现在 action 创建函数 asyncChangeAge 因为返回的是一个对象,其 type 值为 undefined 所以当我们点击按钮时 reducer 将会一直匹配到默认情况,返回的将是当前的状态,接下来我们先让我们的 action 创建函数 asyncChangeAge 生效,达到异步修改状态的作用;

扩展 createStore

  既然 asyncChangeAge 返回的不再是一个 action 对象,而是一个函数;那么其实我们要做的事情是很简单的,我们只需要针对 createStore 中的返回值 dispatch 进行一个简单的扩展即可;通过判断 dispatch 中的 action 参数是否是函数而进行不同的操作:

// redux.js
export const createStore = (reducer) => {
......
// 在createStore 我们对返回值 dispatch 进行了封装
const dispatchExtend = (action) => {
if(typeof action === 'function'){
// action 为函数,执行函数
action(dispatch, getState);
} else {
// action 为非函数(对象)调用dispatch
dispatch(action);
}
}
return {getState, dispatch: dispatchExtend, subscribe};
}

5.3 抽离封装

  上文我们通过对 createStore 的返回值 dispatch 进行了扩展,实现了 redux-react 的异步操作,但问题是我们将代码写死在 createStore 中了,redux-react 的异步操作应该是一个可选项而不应该是必选项;

重新扩展 createStore :

  新增参数 middleware (函数), 在函数 createStore 开始位置判断 middleware 是否存在,存在则执行;

// redux.js
export const createStore = (reducer, middleware) => {
// 判断 middleware 是否存在,存在则执行
if(middleware){
return middleware(createStore)(reducer);
}
let state;
const listeners = [];
const getState = () => {
return state;
}
const dispatch = (action) => {
state = reducer(state, action);
listeners.forEach(v => v());
}
const subscribe = (listener) => {
listeners.push(listener);
}
dispatch({type: '%$&HJKAJJHDJHJ'});
return {getState, dispatch, subscribe};
}

编写函数 applyMiddleware ,在创建 store 时 作为 createStore 第二参数

// App.js
const applyMiddleware = (createStore) => (redux)=> {
// 在这里进行创建 store
const store = createStore(redux);
// 返回store
return {...store}
}
const store = createStore(reducer, applyMiddleware);

在 applyMiddleware 函数内扩展 dispatch

  上文 applyMiddleware 函数并其实没做任何事情, 只是在 createStore 函数外面套了一层函数,那么接下来我们做点正事,来扩展一下我们的 dispatch

// App.js
const applyMiddleware = (createStore) => (redux)=> {
const store = createStore(redux);
const midApi = {
getState: store.getState,
dispatch: (...args) => {dispatch(...args);}
};
const dispatch = (action) => {
if( typeof action === 'function' ){
action(midApi.dispatch, midApi.getState);
} else {
store.dispatch(action);
}
}
return {
...store,
dispatch
};
}

现在我们来看看效果:

《redux以及react-redux简单实现》

5.4 扩展分离

  上文已经实现了我们想要的效果了,我们在 applyMiddleware 对 dispatch 进行了扩展;然而我们是那么容易满足的嘛,当然不是的!! applyMiddleware 中对 dispatch 的扩展我们还可以将其单独提出来封装成一个函数;

重写 applyMiddleware ,再给 applyMiddleware 包裹一层函数: 将对 dispatch 的扩展抽离,封装成方法;

// App.js
const applyMiddleware = (middleware) => (createStore) => (redux)=> {
const store = createStore(redux);
const midApi = {
getState: store.getState,
dispatch: (...args) => {dispatch(...args);}
};
const dispatch = middleware(midApi)(store.dispatch);
return {
...store,
dispatch
};
}

thunk 中间件: 其实 thunk 才是真正的中间件;applyMiddleware 只是用来绑定中间件的

// App.js
const thunk = ({dispatch, getState}) => next => (action) => {
if(typeof action === 'function'){
action(dispatch, getState);
} else {
next(action);
}
};

在调用 createStore 时绑定中间件 thunk

// App.jsx
const store = createStore(reducer, applyMiddleware(thunk));

5.5 代码整理

  这一步只是将 applyMiddleware 函数移到 redux.js 文件中;同时将 thunk 函数写到文件 thunk.jsx 中,然后在 App.js 中引用 applyMiddleware 以及 thunk 而已;

看下最终效果(效果和上一个录屏是一样样的)

《redux以及react-redux简单实现》


推荐阅读
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
author-avatar
平凡屋之换
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有