洛阳设计网站公司,网站左侧导航栏设计,如何用文件传输协议登陆网站,手机怎么注册自己的网站React学习[四] 4 应急方案4.1 使用ref引用值4.1.1 给组件添加ref4.1.2 ref和state的不同之处4.1.3 何时使用ref 4.2 使用ref操作DOM4.2.1 获取指向节点的ref4.2.3 使用 ref 回调管理 ref 列表4.2.4 访问另一个组件的DOM节点4.2.5 用 flushSync 同步更新 state 4.3 使用Effect同… React学习[四] 4 应急方案4.1 使用ref引用值4.1.1 给组件添加ref4.1.2 ref和state的不同之处4.1.3 何时使用ref 4.2 使用ref操作DOM4.2.1 获取指向节点的ref4.2.3 使用 ref 回调管理 ref 列表4.2.4 访问另一个组件的DOM节点4.2.5 用 flushSync 同步更新 state 4.3 使用Effect同步4.4 不需要Effect的情况4.5 响应式Effect的生命周期4.5.1 effect的生命周期4.5.2 Effect只应该依赖变量 4.6 将事件从Effect中分开4.6.1 在事件处理函数和Effect中做选择4.6.2 从Effect中提取非响应式逻辑4.6.3 使用Effect Event 读取最新的props和state 4.7 移除Effect依赖4.7.1 依赖应该和代码保持一致4.7.2 移除非必须的依赖 4.8 使用自定义Hook复用逻辑4.8.1 从组件中提取自定义Hook4.8.2 把事件处理函数传到自定义Hook中4.8.3 什么时候使用自定义Hook 4 应急方案
4.1 使用ref引用值
当希望组件“记住”某些信息但又不想让这些信息触发新的渲染时可以使用 ref 。
4.1.1 给组件添加ref
导入useRef()
import { useRef } from react;调用useRef
const ref useRef(0);可以用 ref.current 属性访问该 ref 的当前值例如
ref.current ref.current 1;设置 state 会重新渲染组件更改 ref 不会当一条信息用于渲染时将它保存在 state 中。当一条信息仅被事件处理器需要并且更改它不需要重新渲染时使用 ref 可能会更高效。
4.1.2 ref和state的不同之处
refstateuseRef(initialValue)返回 { current: initialValue }useRef(initialValue)返回 { current: initialValue }更改时不会触发重新渲染更改时触发重新渲染。可变 —— 可以在渲染过程之外修改和更新 current 的值“不可变” —— 必须使用 state 设置函数来修改 state 变量从而排队重新渲染。不应在渲染期间读取或写入 current 值。可以随时读取 state。但是每次渲染都有自己不变的 state 快照。
4.1.3 何时使用ref
存储timeout Id存储和操作DOM元素存储不需要被用来计算JSX的其他对象
4.2 使用ref操作DOM
有时可能需要访问由 React 管理的 DOM 元素 —— 例如让一个组件获得焦点、滚动到它或测量它的尺寸和位置。在 React 中没有内置的方法来做这些事情所以需要一个指向 DOM 节点的 ref 来实现。
4.2.1 获取指向节点的ref
// 第一步引入Ref
import { useRef } from react;
// 第二步声明一个ref
const myRef useRef(null);
// 第三步将ref传入html标签内比如
div ref{myRef}4.2.3 使用 ref 回调管理 ref 列表
如果需要为列表中的每一项都绑定 ref 而又不知道会有多少项。那么可以将函数传递给ref属性称为ref回调。
import { useRef } from react;export default function CatFriends() {const itemsRef useRef(null);function scrollToId(itemId) {const map getMap();const node map.get(itemId);node.scrollIntoView({behavior: smooth,block: nearest,inline: center});}function getMap() {if (!itemsRef.current) {// 首次运行时初始化 Map。itemsRef.current new Map();}return itemsRef.current;}return (navbutton onClick{() scrollToId(0)}Tom/buttonbutton onClick{() scrollToId(5)}Maru/buttonbutton onClick{() scrollToId(9)}Jellylorum/button/navdivul{catList.map(cat (likey{cat.id}ref{(node) {const map getMap();if (node) {// 添加到 Mapmap.set(cat.id, node);} else {// 从 Map 删除map.delete(cat.id);}}}imgsrc{cat.imageUrl}alt{Cat # cat.id}//li))}/ul/div/);
}const catList [];
for (let i 0; i 10; i) {catList.push({id: i,imageUrl: https://placekitten.com/250/200?image i});
}
4.2.4 访问另一个组件的DOM节点
const MyInput forwardRef((props, ref) {return input {...props} ref{ref} /;
});MyInput ref{inputRef} / 告诉 React 将对应的 DOM 节点放入 inputRef.current 中。但是这取决于 MyInput 组件是否允许这种行为 默认情况下是不允许的。MyInput 组件是使用 forwardRef 声明的。 这让从上面接收的 inputRef 作为第二个参数 ref 传入组件第一个参数是 props 。MyInput 组件将自己接收到的 ref 传递给它内部的 input。
限制暴露的功能:useImperativeHandle。
const MyInput forwardRef((props, ref) {const realInputRef useRef(null);useImperativeHandle(ref, () ({// 只暴露 focus没有别的focus() {realInputRef.current.focus();},}));return input {...props} ref{realInputRef} /;
});
4.2.5 用 flushSync 同步更新 state
如果需要强制 React 同步更新“刷新”DOM。从 react-dom 导入 flushSync 并将 state 更新包裹 到 flushSync 调用中
import { flushSync } from react-dom;
function handleAdd() {const newTodo { id: nextId, text: text };flushSync(() {setText();setTodos([ ...todos, newTodo]); });listRef.current.lastChild.scrollIntoView({behavior: smooth,block: nearest});}Refs 是一个应急方案。应该只在必须“跳出 React”时使用它们。这方面的常见示例包括管理焦点、滚动位置或调用 React 未暴露的浏览器 API。 4.3 使用Effect同步
Effects 会在渲染后运行一些代码以便可以将组件与 React 之外的某些系统同步。不要随意在你的组件中使用 Effect。
三个步骤 声明Effect import { useEffect } from react;function MyComponent() {useEffect(() {// 每次渲染后都会执行此处的代码});return div /;
} 指定Effect依赖。大多数 Effect 应该按需执行而不是在每次渲染后都执行。 useEffect(() {if (isPlaying) { // isPlaying 在此处使用……// ...} else {// ...}}, [isPlaying]); // ……所以它必须在此处声明必要时添加清理(cleanUp)函数。有时 Effect 需要指定如何停止、撤销或者清除它的效果。 空的依赖数组[]对应于组件“挂载”即添加到屏幕上。 useEffect(() {const connection createConnection(); // 开启连接connection.connect();return () {connection.disconnect(); // 断开连接};}, []);控制非React组件
useEffect(() {const dialog dialogRef.current;dialog.showModal();return () dialog.close();
}, []);
订阅事件
如果 Effect 订阅了某些事件清理函数应该退订这些事件
useEffect(() {function handleScroll(e) {console.log(window.scrollX, window.scrollY);}window.addEventListener(scroll, handleScroll);return () window.removeEventListener(scroll, handleScroll);
}, []);触发动画
如果 Effect 对某些内容加入了动画清理函数应将动画重置
useEffect(() {const node ref.current;node.style.opacity 1; // 触发动画return () {node.style.opacity 0; // 重置为初始值};
}, []);获取数据
如果 Effect 将会获取数据清理函数应该要么 中止该数据获取操作要么忽略其结果
useEffect(() {let ignore false;async function startFetching() {const json await fetchTodos(userId);if (!ignore) {setTodos(json);}}startFetching();return () {ignore true;};
}, [userId]);
为了防止条件竞争每个 Effect 都可以在里面设置一个 ignore 标记变量。在最开始ignore 被设置为 false。然而当 Effect 执行清理函数后就像你选中了列表中不同的人时ignore 就会被设置为 true。 仅在严格模式下的开发环境中React 会挂载两次组件以对 Effect 进行压力测试。React 将在下次 Effect 运行之前以及卸载期间这两个时候调用清理函数。 4.4 不需要Effect的情况 根据props或state来更新state 使用useMemo缓存耗时的计算 比如 import { useMemo, useState } from react;function TodoList({ todos, filter }) {const [newTodo, setNewTodo] useState();// ✅ 除非 todos 或 filter 发生变化否则不会重新执行 getFilteredTodos()const visibleTodos useMemo(() getFilteredTodos(todos, filter), [todos, filter]);// ...
}会告诉 React除非 todos 或 filter 发生变化否则不要重新执行传入的函数。 当 props 变化时重置所有 state 。可以使用key属性来标识。 当prop变化时调整部分state // 虽然下面这种方式比 Effect 更高效但大多数组件也不需要它
function List({ items }) {const [isReverse, setIsReverse] useState(false);const [selection, setSelection] useState(null);// 好一些在渲染期间调整 stateconst [prevItems, setPrevItems] useState(items);if (items ! prevItems) {setPrevItems(items);setSelection(null);}// ...
}/* -----------优化在渲染期间计算内容---------- */function List({ items }) {const [isReverse, setIsReverse] useState(false);const [selectedId, setSelectedId] useState(null);// ✅ 非常好在渲染期间计算所需内容const selection items.find(item item.id selectedId) ?? null;// ...
} 检查是否可以通过添加 key 来重置所有 state或者 在渲染期间计算所需内容。 在事件处理函数中共享逻辑 如果有组件用到了共同的函数调用尝试把这个函数抽离出来成为一个独立函数 function ProductPage({ product, addToCart }) {// ✅ 非常好事件特定的逻辑在事件处理函数中处理function buyProduct() {addToCart(product);showNotification(已添加 ${product.name} 进购物车);}function handleBuyClick() {buyProduct();}function handleCheckoutClick() {buyProduct();navigateTo(/checkout);}// ...
}发送Post请求 当用户按下按钮发送post请求只在特定交互中发生 链式计算 初始化应用 每次应用加载时执行一次。可以添加一个顶层变量来记录它是否已经被执行过了。 let didInit false;function App() {useEffect(() {if (!didInit) {didInit true;// ✅ 只在每次应用加载时执行一次loadDataFromLocalStorage();checkAuthToken();}}, []);// ...
}或者在模块初始化和应用渲染之前执行 if (typeof window ! undefined) { // 检测我们是否在浏览器环境// ✅ 只在每次应用加载时执行一次checkAuthToken();loadDataFromLocalStorage();
}function App() {// ...
}为了避免在导入任意组件时降低性能或产生意外行为请不要过度使用这种方法。将应用级别的初始化逻辑保留在像 App.js 这样的根组件模块或你的应用入口中。 通知父组件有关state变化的信息 可以试试状态提升由父组件控制state 将数据传递给父组件
可以让父组件获取数据并传递给子组件 订阅外部store 利用react的Hook函数useSyncExternalStore function subscribe(callback) {window.addEventListener(online, callback);window.addEventListener(offline, callback);return () {window.removeEventListener(online, callback);window.removeEventListener(offline, callback);};
}function useOnlineStatus() {// ✅ 非常好用内置的 Hook 订阅外部 storereturn useSyncExternalStore(subscribe, // 只要传递的是同一个函数React 不会重新订阅() navigator.onLine, // 如何在客户端获取值() true // 如何在服务端获取值);
}function ChatIndicator() {const isOnline useOnlineStatus();// ...
}获取数据 为了避免条件竞争情况的出现需要在effect中添加清理函数来忽略较早的返回结果. function SearchResults({ query }) {const [results, setResults] useState([]);const [page, setPage] useState(1);useEffect(() {let ignore false;fetchResults(query, page).then(json {if (!ignore) {setResults(json);}});return () {ignore true;};}, [query, page]);function handleNextPageClick() {setPage(page 1);}// ...
}比使用effect更好的办法是使用框架的内置数据获取机制 4.5 响应式Effect的生命周期
4.5.1 effect的生命周期
每个react组件都经历相同的生命周期
组件挂载组件更新组件卸载
但是effect不一样Effect 能够在需要时始终具备启动和停止的弹性。
React会通过在开发环境中立即强制 Effect 重新进行同步来验证其是否能够重新同步。而之所以知道需要重新同步是因为effect的依赖项发生了变化。
**代码中的每个 Effect 应该代表一个独立的同步过程。**也就是说删除一个 Effect 不会影响另一个 Effect 的逻辑。
4.5.2 Effect只应该依赖变量
Effect的依赖项是变量变量发生改变后effect会重新响应。
如果effect没有依赖项就表明这个effect仅在组件挂载时执行一次并在组件卸载时清理。
组件内部的所有值包括 props、state 和组件体内的变量都是响应式的。任何响应式值都可以在重新渲染时发生变化所以需要将响应式值包括在 Effect 的依赖项中。 全局变量或可变值不可以作为依赖。应该使用 useSyncExternalStore 来读取和订阅外部可变值。 如果出现无限循环的问题或者 Effect 过于频繁地重新进行同步可以尝试以下解决方案
检查Effect是否表示了独立的同步过程。如果想读取 props 或 state 的最新值但又不想对其做出反应并重新同步 Effect可以将 Effect 拆分为具有反应性的部分保留在 Effect 中和非反应性的部分提取为名为 “Effect Event” 的内容避免将对象和函数作为依赖项
挑战一个下拉框允许用户选择一个行星而另一个下拉框应该显示该选定行星上的地点。然而目前这两个下拉框都还没有正常工作。你的任务是添加一些额外的代码使得选择一个行星时placeList 状态变量被填充为 /planets/ planetId /places API 调用的结果。
App.js
import { useState, useEffect } from react;
import { fetchData } from ./api.js;export default function Page() {const [planetList, setPlanetList] useState([])const [planetId, setPlanetId] useState();const [placeList, setPlaceList] useState([]);const [placeId, setPlaceId] useState();useEffect(() {let ignore false;fetchData(/planets).then(result {if (!ignore) {console.log(获取了一个行星列表。);setPlanetList(result);setPlanetId(result[0].id); // 选择第一个行星}});return () {ignore true;}}, []);useEffect(() {if (planetId ) {return;}let ignore false;fetchData(/planets/ planetId /places).then(result {if (!ignore) {console.log(获取了该行星的地点列表);setPlaceList(result);setPlaceId(result[0].id);}});return () {ignore true;}}, [planetId])return (label选择一个行星{ }select value{planetId} onChange{e {setPlanetId(e.target.value);}}{planetList?.map(planet option key{planet.id} value{planet.id}{planet.name}/option)}/select/labellabel选择一个地点{ }select value{placeId} onChange{e {setPlaceId(e.target.value);}}{placeList?.map(place option key{place.id} value{place.id}{place.name}/option)}/select/labelhr /p你将要前往{planetId || ...} 的 {placeId || ...} /p/);
} 理想情况下应用程序中的大多数 Effect 最终都应该由自定义 Hook 替代无论是由你自己编写还是由社区提供。为了减少一些重复可以把一些逻辑提取到自定义Hook中。
App.js
import { useState } from react;
import { useSelectOptions } from ./useSelectOptions.js;export default function Page() {const [planetList,planetId,setPlanetId] useSelectOptions(/planets);const [placeList,placeId,setPlaceId] useSelectOptions(planetId ? /planets/${planetId}/places : null);return (label选择一个行星{ }select value{planetId} onChange{e {setPlanetId(e.target.value);}}{planetList?.map(planet option key{planet.id} value{planet.id}{planet.name}/option)}/select/labellabel选择一个地点{ }select value{placeId} onChange{e {setPlaceId(e.target.value);}}{placeList?.map(place option key{place.id} value{place.id}{place.name}/option)}/select/labelhr /p你将要前往{planetId || ...} 的 {placeId || ...} /p/);
}
useSelectOptions.js
import { useState, useEffect } from react;
import { fetchData } from ./api.js;export function useSelectOptions(url) {const [list, setList] useState(null);const [selectedId, setSelectedId] useState();useEffect(() {if (url null) {return;}let ignore false;fetchData(url).then(result {if (!ignore) {setList(result);setSelectedId(result[0].id);}});return () {ignore true;}}, [url]);return [list, selectedId, setSelectedId];
} 4.6 将事件从Effect中分开
4.6.1 在事件处理函数和Effect中做选择
事件处理函数
只在响应特定的交互操作时运行事件处理函数内部的逻辑是非响应式的
Effect
需要同步时比如保持服务器连接Effect内部的逻辑是响应式的
组件内部声明的 state 和 props 变量被称为响应式值。这些响应式值参与组件的渲染数据流。
4.6.2 从Effect中提取非响应式逻辑
声明一个Effect Event尚未发布到React正式版中截至2023.8.15。
import { useEffect, useEffectEvent } from react;function ChatRoom({ roomId, theme }) {const onConnected useEffectEvent(() {showNotification(Connected!, theme);});之后可以在Effect内部调用onConnected:
function ChatRoom({ roomId, theme }) {const onConnected useEffectEvent(() {showNotification(Connected!, theme);});useEffect(() {const connection createConnection(serverUrl, roomId);connection.on(connected, () {onConnected();});connection.connect();return () connection.disconnect();}, [roomId]); // ✅ 声明所有依赖项4.6.3 使用Effect Event 读取最新的props和state
尚未发布到React正式版中截至2023.8.15。
function Page({ url }) {const { items } useContext(ShoppingCartContext);const numberOfItems items.length;const onVisit useEffectEvent(visitedUrl {logVisit(visitedUrl, numberOfItems);});useEffect(() {onVisit(url);}, [url]); // ✅ 声明所有依赖项// ...
}这里的 onVisit 是一个 Effect Event。里面的代码不是响应式的。另一方面Effect 本身仍然是响应式的。其内部的代码使用了 url props所以每次因为不同的 url 重新渲染后 Effect 都会重新运行。这会依次调用 onVisit 这个 Effect Event。
Effect Event 的局限性在于你如何使用他们
只在 Effect 内部调用他们。永远不要把他们传给其他的组件或者 Hook。 4.7 移除Effect依赖
4.7.1 依赖应该和代码保持一致
编写 Effect 时无论这个 Effect 要做什么首先要明确其生命周期什么时候同步什么时候需要清理。确保Effect的依赖项与函数代码里的变量一致。每个被Effect使用的响应值必须在依赖中声明。要移除一个依赖需要向linter证明其不需要这个依赖。要改变依赖也要考虑代码需不需要改变。
**建议将依赖性 lint 错误作为一个编译错误来处理。**不然有可能会遇到你并不知道是什么的bug。
4.7.2 移除非必须的依赖
需要考虑的问题 这段代码应该移到事件处理程序中吗 避免Effect 中有特定的事件处理逻辑代码。 Effect是否在做几件不相关的事情 每个effect应该代表一个独立的同步过程。如果担心代码重复可以提取相同逻辑到自定义Hook来提升代码质量。 是否在读取一些状态来计算下一个状态 将非响应式逻辑移至Effect Event中正式版未发布 用 Effect Event 包装来自props的事件处理程序 尽可能避免将对象和函数作为 Effect 的依赖 将静态对象和函数移除组件 将动态对象和函数移动到effect中 从对象中读取原始值 从 Effect 外部 读取对象信息并避免依赖对象和函数类型 function ChatRoom({ options }) {const [message, setMessage] useState();const { roomId, serverUrl } options;useEffect(() {const connection createConnection({roomId: roomId,serverUrl: serverUrl});connection.connect();return () connection.disconnect();}, [roomId, serverUrl]); // ✅ 所有依赖已声明// ...从函数中计算原始值
假设父组件传了一个函数
ChatRoomroomId{roomId}getOptions{() {return {serverUrl: serverUrl,roomId: roomId};}}
/为避免使其成为依赖并导致它在重新渲染时重新连接需要在 Effect 外部调用它
function ChatRoom({ getOptions }) {const [message, setMessage] useState();const { roomId, serverUrl } getOptions();useEffect(() {const connection createConnection({roomId: roomId,serverUrl: serverUrl});connection.connect();return () connection.disconnect();}, [roomId, serverUrl]); // ✅ 所有依赖已声明// ...这仅适用于 纯函数因为它们在渲染期间可以安全调用。如果函数是一个事件处理程序但你不希望它的更改重新同步 Effect将它包装到 Effect Event 中。
4.8 使用自定义Hook复用逻辑
4.8.1 从组件中提取自定义Hook
如果一个Effect中的逻辑有多个组件用到了就可以考虑将重复逻辑部分提取出来。
Hook的名称必须以’use’开头
自定义Hook共享的是状态逻辑而不是状态本身。对同一个 Hook 的每个调用是各自完全独立的。
4.8.2 把事件处理函数传到自定义Hook中
使用了useEffect
import { useEffect, useEffectEvent } from react;
// ...export function useChatRoom({ serverUrl, roomId, onReceiveMessage }) {const onMessage useEffectEvent(onReceiveMessage);useEffect(() {const options {serverUrl: serverUrl,roomId: roomId};const connection createConnection(options);connection.connect();connection.on(message, (msg) {onMessage(msg);});return () connection.disconnect();}, [roomId, serverUrl]); // ✅ 声明所有依赖
}4.8.3 什么时候使用自定义Hook
首先明白一件事就是如果你需要写Effect就意味着需要走出React和某些外部系统同步或者需要做一些react中没有对应内置API的事。
使用自定义Hook时需要专注于高级用例避免使用react生命周期比如useMount每个自定义Hook应该专注于实现一个功能。
把Effect包裹进自定义Hook有益的另一些原因
让进出 Effect 的数据流非常清晰。让组件专注于目标而不是 Effect 的准确实现。当 React 增加新特性时可以在不修改任何组件的情况下移除这些 Effect。 文章转载自: http://www.morning.nfbkz.cn.gov.cn.nfbkz.cn http://www.morning.bryyb.cn.gov.cn.bryyb.cn http://www.morning.pgxjl.cn.gov.cn.pgxjl.cn http://www.morning.tpchy.cn.gov.cn.tpchy.cn http://www.morning.wmmtl.cn.gov.cn.wmmtl.cn http://www.morning.jnvivi.com.gov.cn.jnvivi.com http://www.morning.lznqb.cn.gov.cn.lznqb.cn http://www.morning.fcwxs.cn.gov.cn.fcwxs.cn http://www.morning.rpkl.cn.gov.cn.rpkl.cn http://www.morning.syglx.cn.gov.cn.syglx.cn http://www.morning.qlznd.cn.gov.cn.qlznd.cn http://www.morning.sbrpz.cn.gov.cn.sbrpz.cn http://www.morning.pybqq.cn.gov.cn.pybqq.cn http://www.morning.nrmyj.cn.gov.cn.nrmyj.cn http://www.morning.rjrlx.cn.gov.cn.rjrlx.cn http://www.morning.wsjnr.cn.gov.cn.wsjnr.cn http://www.morning.dpplr.cn.gov.cn.dpplr.cn http://www.morning.pcshb.cn.gov.cn.pcshb.cn http://www.morning.gqwbl.cn.gov.cn.gqwbl.cn http://www.morning.byjwl.cn.gov.cn.byjwl.cn http://www.morning.zstbc.cn.gov.cn.zstbc.cn http://www.morning.kwnnx.cn.gov.cn.kwnnx.cn http://www.morning.vjdofuj.cn.gov.cn.vjdofuj.cn http://www.morning.nrjr.cn.gov.cn.nrjr.cn http://www.morning.gfpyy.cn.gov.cn.gfpyy.cn http://www.morning.mzrqj.cn.gov.cn.mzrqj.cn http://www.morning.xoaz.cn.gov.cn.xoaz.cn http://www.morning.wbnsf.cn.gov.cn.wbnsf.cn http://www.morning.jbxd.cn.gov.cn.jbxd.cn http://www.morning.lhptg.cn.gov.cn.lhptg.cn http://www.morning.lclpj.cn.gov.cn.lclpj.cn http://www.morning.qwhbk.cn.gov.cn.qwhbk.cn http://www.morning.mywnk.cn.gov.cn.mywnk.cn http://www.morning.ktmpw.cn.gov.cn.ktmpw.cn http://www.morning.pycpt.cn.gov.cn.pycpt.cn http://www.morning.qieistand.com.gov.cn.qieistand.com http://www.morning.mzwqt.cn.gov.cn.mzwqt.cn http://www.morning.wgrm.cn.gov.cn.wgrm.cn http://www.morning.kfqzd.cn.gov.cn.kfqzd.cn http://www.morning.fchkc.cn.gov.cn.fchkc.cn http://www.morning.jxmjr.cn.gov.cn.jxmjr.cn http://www.morning.hxxyp.cn.gov.cn.hxxyp.cn http://www.morning.fqyxb.cn.gov.cn.fqyxb.cn http://www.morning.ygxf.cn.gov.cn.ygxf.cn http://www.morning.khxwp.cn.gov.cn.khxwp.cn http://www.morning.dkmzr.cn.gov.cn.dkmzr.cn http://www.morning.nxwk.cn.gov.cn.nxwk.cn http://www.morning.ylkkh.cn.gov.cn.ylkkh.cn http://www.morning.ysnbq.cn.gov.cn.ysnbq.cn http://www.morning.dygqq.cn.gov.cn.dygqq.cn http://www.morning.trjp.cn.gov.cn.trjp.cn http://www.morning.qhmql.cn.gov.cn.qhmql.cn http://www.morning.mtsgx.cn.gov.cn.mtsgx.cn http://www.morning.clhyj.cn.gov.cn.clhyj.cn http://www.morning.mdwlg.cn.gov.cn.mdwlg.cn http://www.morning.cokcb.cn.gov.cn.cokcb.cn http://www.morning.mngh.cn.gov.cn.mngh.cn http://www.morning.mlpch.cn.gov.cn.mlpch.cn http://www.morning.xmttd.cn.gov.cn.xmttd.cn http://www.morning.kwnbd.cn.gov.cn.kwnbd.cn http://www.morning.srgbr.cn.gov.cn.srgbr.cn http://www.morning.zsyqg.cn.gov.cn.zsyqg.cn http://www.morning.xpqdf.cn.gov.cn.xpqdf.cn http://www.morning.rtpw.cn.gov.cn.rtpw.cn http://www.morning.3jiax.cn.gov.cn.3jiax.cn http://www.morning.pqqzd.cn.gov.cn.pqqzd.cn http://www.morning.xhrws.cn.gov.cn.xhrws.cn http://www.morning.lsfrc.cn.gov.cn.lsfrc.cn http://www.morning.mzcsp.cn.gov.cn.mzcsp.cn http://www.morning.tjqcfw.cn.gov.cn.tjqcfw.cn http://www.morning.stbfy.cn.gov.cn.stbfy.cn http://www.morning.xqjz.cn.gov.cn.xqjz.cn http://www.morning.qjldz.cn.gov.cn.qjldz.cn http://www.morning.tbksk.cn.gov.cn.tbksk.cn http://www.morning.qcslh.cn.gov.cn.qcslh.cn http://www.morning.gynlc.cn.gov.cn.gynlc.cn http://www.morning.rqrxh.cn.gov.cn.rqrxh.cn http://www.morning.pdkht.cn.gov.cn.pdkht.cn http://www.morning.sltfk.cn.gov.cn.sltfk.cn http://www.morning.pynzj.cn.gov.cn.pynzj.cn