{"id":20719014,"url":"https://github.com/dlyt/ycool","last_synced_at":"2025-08-21T03:32:23.889Z","repository":{"id":189057786,"uuid":"85087148","full_name":"dlyt/YCool","owner":"dlyt","description":"小说阅读APP","archived":false,"fork":false,"pushed_at":"2017-10-24T01:31:52.000Z","size":11831,"stargazers_count":202,"open_issues_count":1,"forks_count":65,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-12-12T18:23:30.681Z","etag":null,"topics":["novel","react-native","redux"],"latest_commit_sha":null,"homepage":"https://github.com/dlyt/YCool_Server","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dlyt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-03-15T15:10:49.000Z","updated_at":"2024-07-05T19:24:11.000Z","dependencies_parsed_at":null,"dependency_job_id":"d13d2184-35c5-4713-97af-af059e88365e","html_url":"https://github.com/dlyt/YCool","commit_stats":null,"previous_names":["dlyt/ycool"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlyt%2FYCool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlyt%2FYCool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlyt%2FYCool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dlyt%2FYCool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dlyt","download_url":"https://codeload.github.com/dlyt/YCool/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230487843,"owners_count":18233865,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["novel","react-native","redux"],"created_at":"2024-11-17T03:15:40.081Z","updated_at":"2024-12-19T19:07:29.800Z","avatar_url":"https://github.com/dlyt.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 简介\n这是一个用React Native写的小说APP，支持搜索小说、订阅小说、在线阅读。\n\n后台API服务器代码地址：https://github.com/dlyt/YCool_Server.git\n## 效果图\n![Octicons](http://i4.bvimg.com/1949/acdbf4a368ecdbb5.gif)\n## 目录结构\n```\n.\n├── app                       # 程序源文件         \n│   ├── actions               # actions\n│   ├── containers            # 容器\n│   ├── imgs                  # 图片\n│   ├── lib                   # 工具文件夹\n│   └── reducers              # reducers\n└── index.ios.js              # 程序入口文件\n```\n## 技术栈\n1.导航系统 NavigationExperimental\n- NavigationRootContainer允许导航的各个状态(屏幕）保存在app的最顶层。\n  - 使用reducer在导航状态中声明设置转换过渡\n  - 可以将state永久保存存到硬盘，这样刷新和app更新后，还能获得之前的导航状态\n  - 监听打开中的url链接，BackAndroid便于支持返回按纽\n- NavigationReducers 包含了预置的reducers, 用来管理导航状态之间的转换过渡。\n  - Reducers可以彼此之前进行组合，设置更高级的导航逻辑\n- 导航逻辑可以用于任何的视图\n- NavigationAnimatedView 是一个用来管理不同场景动画的组件，也可以用于Navigator和NavigatorIOS组件 \n - 每一个scene可以完全自定义，并且管理它自己的动画和手势\n - 可以有一个Overlay/header, 用于跟场景的动画同步\n- NavigationCard 和NavigationHeader可以作为预编译的scenes和overlays. 然后跟NavigationAnimatedView一起使用\n\n2.数据管理 redux\n\n应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中。惟一改变 state 的办法是触发 action，一个描述发生什么的对象。为了描述 action 如何改变 state 树，你需要编写 reducers。\n\naction和reducers的代码写在相应文件夹里，可以到项目中去看，下面是注册store的代码。\n\nindex.ios.js\n```js\nconst App = () =\u003e (\n  \u003cProvider store={store}\u003e\n    \u003cAppContainer /\u003e\n  \u003c/Provider\u003e\n)\n\nAppRegistry.registerComponent('YCool', () =\u003e App)\n```\n\n3.数据请求\n\n`axios`\n\n统一设置token验证信息：\n\napp/lib/setAuthorizationToken.js\n```js\nimport axios from 'axios'\n\nexport default function setAuthorizationToken(token) {\n  if (token) {\n    axios.defaults.headers.common['Authorization'] = `Bearer ${token}`\n  } else {\n    delete axios.defaults.headers.common['Authorization']\n  }\n}\n```\n\n4.中间件 redux-thunk, redux-logger\n\n下面是一段登录的action，来说明`redux-thunk`的用处\n```js\nexport function login(user) {\n  return dispatch =\u003e {\n    return axios.post('/api/auth', user).then(res =\u003e {\n      const token = res.data.token\n      localStorage.setItem('jwtToken', token)\n      setAuthorizationToken(token)\n      dispatch(setCurrentUser(jwtDecode(token)))\n    })\n  }\n}\n```\n如果不添加 redux-thunk 这个中间件这段代码是会保错的，提示如下：\n```js\nActions must be plain objects. Use custom middleware for async actions.\n```\n这里，要先知道：\n\n通过使用指定的 middleware，action 创建函数除了返回 action 对象外还可以返回函数。这时，这个 action 创建函数就成为了 thunk。\n\n下面的代码更容易我们理解\n```js\nconst foo = () =\u003e {\n\tlet bar = 'before'\n\tsetTimeout(() =\u003e {\n    bar = 'after'\n  }, 3000)\n  return {\n  \tbar\n  }\n}\n\ndocument.getElementById('demo').innerHTML = foo().bar\n```\n由于 foo 中回传的 bar 在 return 之时是为 'before' ,并不会等到 setTimeout 结束后在被 assign 的 'after'。\n\n如果不引入 thunk 它只有同步操作。每当 dispatch action 时，state 会被立即更新。这时候使用异步操作就会报错。\n\n我们解决这个问题就可以使用 redux-thunk ，它是通过中间件（middleware）的形式被引用。\n\n这句话有助于你理解 middleware： `它提供的是位于 action 被发起之后，到达 reducer 之前的扩展点。`\n\nmiddleware 改造了你的 dispatch ，让它有能力判断送进去的东西是一个 pure object 还是 function 。\n\n我们先看一下 redux-thunk 是如何使用的。\n```js\nimport thunkMiddleware from 'redux-thunk'\nconst store = createStore(\n  reducers,\n  compose(\n    applyMiddleware(\n      thunkMiddleware,    // 允许我们 dispatch() 函数\n      loggerMiddleware    // 一个很便捷的 middleware，用来打印 action 日志\n    ),\n  )\n)\n```\nredux-thunk 的源码中，首先判断是否是 function :\n```js\nif (typeof action === 'function'){}\n```\n如果不是 function ，那自然就是一个 pure object ,利用 next 送出，什么也不需要做；若是 function ,则把这个 thunk 需要的 dispatch , getState 和其他 arguement 传给 thunk ,让它做你所指定它做的事情。\n\nredux-logger 这个中间件会在控制台打印出 action 如图，有助于开发。\n![](http://cdn.tycocn.com/react-login.png)\n\n## 功能列表\n- [x] 下拉刷新\n- [x] 左滑删除\n## 安装\n```bash\ngit clone https://github.com/dlyt/YCool.git\nnpm install\n```\n注意导入的2个包\n\n  react-native-device-info 需要配置\n\n    1. 右击选择项目名称 选择Add Files to '你的项目名'\n    2. 进入node_modules/react-native-device-info\n    3. 添加 .xcodeproj文件\n    4. 在Xcode中点击你的工程名字——\u003eBuild Phases——\u003eLink Binary With Libraries——\u003e点击 '+'号按钮，添加libRNDeviceInfo.a文件\n\n  react-native-swipeout 需要替换一下这个包里的index.js文件\n\n  [index.js.zip](https://github.com/dancormier/react-native-swipeout/files/340703/index.js.zip)\n## 开发环境\nIOS  6S\n## License\n仅供学习使用\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdlyt%2Fycool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdlyt%2Fycool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdlyt%2Fycool/lists"}