简述商务网站建设步骤,配置外网访问WordPress,wep开发和网站开发,付费电影怎样免费观看文章目录1 什么是设计模式#xff1f;2 发布-订阅模式2.1 DOM事件2.2 基于Broadcast Channel实现跨页面通信2.3 基于localStorage实现跨页面通信2.4 使用 Vue 的 EventBus 进行跨组件通信2.4 使用 React 的 EventEmitter 进行跨组件通信3 装饰器模式3.1 React 高阶组件 HOC3.2…
文章目录1 什么是设计模式2 发布-订阅模式2.1 DOM事件2.2 基于Broadcast Channel实现跨页面通信2.3 基于localStorage实现跨页面通信2.4 使用 Vue 的 EventBus 进行跨组件通信2.4 使用 React 的 EventEmitter 进行跨组件通信3 装饰器模式3.1 React 高阶组件 HOC3.2 AOP 面向切面编程3.3 axios调用时添加token4 单例模式4.1 惰性单例4.2 通用的惰性单例4.3 Vuex 数据缓存4.4 antd/message4.5 axios取消重复请求5 策略模式5.1 JavaScript版本的策略模式5.2 axios6 迭代器模式6.1 JS中的迭代器6.2 根据不同浏览器选择相应的上传组件7 代理模式7.1 虚拟代理合并HTTP请求7.2 缓存代理7.3 Vue中的代理模式1 什么是设计模式
设计模式是针对开发中遇到的问题提出的公认且有效的解决方案。共23种设计模式。
2 发布-订阅模式 对象间的一种一对多的依赖关系当一个对象的状态发生改变时所有依赖它的对象都将得到通知
消息的发布者将消息通过消息通道广播出去然后订阅者通过订阅获取到想要的消息。
2.1 DOM事件
funtion func() {console.log(2)
}// 添加订阅者
document.body.addEventListener(click, func, false)// 删除订阅者
document.body.removeEventListener(click, func)这里我们就订阅document.body上的click事件当body被点击时body节点便会向订阅者发布这个消息当然我们还可以随意的添加或者删除订阅者
2.2 基于Broadcast Channel实现跨页面通信
// A页面监听广播
// 第一步 创建实例
const bc new BroadcastChannel(myBroadcastChannel)
// 第二部 通过onmessage设置回调事件
bc.onmessage e {console.log(e.data)
}// B页面发送广播
const bc new BroadcastChannel(myBroadcastChannel)
bc.postMessage(hollow word)// 关闭广播
bc.close()2.3 基于localStorage实现跨页面通信
// http://localhost:8080/A.html
window.addEventListener(storage, e {// e.key 改变的key值 - msg// e.oldValue 改变前的值// e.newValue 改变后的值 - 哈哈哈if (e.key msg) { ... }
})// http://localhost:8080/B.html
localStorage.setItem(msg, 哈哈哈)2.4 使用 Vue 的 EventBus 进行跨组件通信
创建一个EventBus (本质上是Vue的一个实例对象)
import Vue from vux
const EventBus new Vue()
export default EventBus接着在组件A和组件B中引入bus.jsimport Bus from /utils/bus组件A在 mounted 钩子中调用 Bus 的注册订阅方法 $on 传入订阅主题和回调方法组件B中在点击事件中发布主题让订阅该主题的组件执行回调方法。
// 组件A
mounted () {// 订阅Bus.$on(SayHollow, text {console.log(text)})
}// 组件B
methods: {clickEvent () {// 发布Bus.$emit(SayHollow, 啊俊俊)}
}2.4 使用 React 的 EventEmitter 进行跨组件通信
import React, { Component } from react
//一 导入EventEmitter
import { EventEmitter } from events;//二 构建事件实例
const EventBus EventEmitter()//tips:我们可以在多个组件中去增加同一个事件的订阅这里仅仅是示例
class Observer extends Component {componentDidMount () {// 三: 增加事件订阅this.event1 EventBus.addListener(someEvent, (params) {console.log(params)})}componentWillUnMount () {//四: 移除事件订阅EventBus.removeListener(this.event1)}render () {return (div事件监听组件/div)}
}
class Publisher extends Component {handleClick () {const params {}//五: 发布事件(当someEvent发布时订阅该事件的函数就会执行)EventBus.emit(someEvent, params)}render () {return (divbutton onClick{this.handleClick.bind(this)}发布事件/button/div)}
}
3 装饰器模式
装饰器模式动态的给某个对象添加一些职责并且不会影响从这个类派生的其他对象。
在传统的面向对象开发中给对象添加功能时我们通常会采用继承的方式继承的方式目的是为了复用但是随之而来也带来一些问题 1父类和子类存在强耦合的关系当父类改变时子类也需要改变 2子类需要知道父类中的细节至少需要知道接口名从而进行复用或复写这样其实破坏了封装性 3继承的方式可能会创建出大量子类。比如现在有BBA三种类型的汽车构造了一个汽车基类三个三种类型的汽车。现在需要给汽车装上雾灯、前大灯、导航仪、刮雨器如果采用继承的方式那么就要构建3*4个类。但是如果把雾灯、前大灯、导航仪、刮雨器动态地添加到汽车上那么只需要增加4个类。这种采用动态添加职责的方式就是装饰器。
装饰器的目的就是在不改变原来类的基础上为其在运行期间动态的添加职责。
提高编程的低耦合与高可复用性
3.1 React 高阶组件 HOC
import React from react;const yellowHOC WrapperComponent {return class extends React.Component {render() {div style{{ backgroundColor: yellow }}WrapperComponent {...this.props} //div;}};
};export default yellowHOC;import React from react;
import yellowHOC from ./yellowHOC;class TargetComponent extends Reac.Compoment {render() {return div66666/div;}
}export default yellowHOC(TargetComponent);3.2 AOP 面向切面编程
业务和系统基础功能分离用 Decorator 很合适
log装饰器实现
export function log(target, name, decriptor) {var _origin decriptor.value;decriptor.value function () {console.log(Calling ${name} with , arguments);return _origin.apply(null, arguments);};return decriptor;
}调用装饰器
import { log } from ./log;
class Person {logsay(nick) {return hi ${nick};}
}var person new Person();
person.say(小明);3.3 axios调用时添加token
4 单例模式
保证一个类仅有一个实例并提供一个访问它的全局访问点
避免重复的创建实例节约不必要的开销。通常会在第三方库的开发中使用到。如果是项目的开发单例模式也会用在一些数据缓存、全局通用弹窗如登录弹窗等一些场景中。
4.1 惰性单例
惰性单例指的是在需要的时候才创建对象实例。通常会用在全局唯一且非必需的一些场景例如全局弹窗、购物车列表、全局共同信息等场景。
拿书中登录弹窗的例子可以理解的更加清晰
var createLoginLayer (function() {var div;return function() {if(!div) {div document.createElement(div);div.innerHtml 登录弹窗;div.style.display none;document.body.appendChild(div);}return div;}
})()document.getElementById(loginBtn).onclick function() {var loginLayer createLoginLayer();loginLayer.style.display block;
}在这个例子中只有在登录按钮点击时才会去创建登录弹窗dom节点而不是在页面加载时就默认创建并且只有在第一次执行时创建登录弹窗dom节点再次执行也不会创建多余的节点节省了一部分性能。
4.2 通用的惰性单例
上面代码在createLoginLayer方法中既实现了单例的逻辑也实现了创建登录弹窗的逻辑。这违反了上节介绍的单一职责原则如果下次仍然需要创建另一个弹窗或其他的功能我们仍然需要将创建单例这部分逻辑再次抄一遍。这么一说相信大家也能理解到这段代码需要如何进行拆分了将不变的部分抽离出来也就是将要介绍的通用的惰性单例 // 通用的惰性单例
var getSingle function(fn) {var result;return function() {return result || (resule fn.apply(this, arguments));}
}// 创建登录弹窗的方法就可以改写成
var createLoginLayer function() {var div document.createElement(div);div.innerHtml 登录弹窗;div.style.display none;document.body.appendChild(div);return div;
}var createSingleLoginLayer getSingle(createLoginLayer);document.getElementById(loginBtn).onclick function() {var loginLayer createSingleLoginLayer();loginLayer.style.display block;
}如上面代码我们将创建登录弹窗和单例的逻辑分离成createLoginLayer和getSingle这样之后再有了类似的需求就可以复用到getSingle方法实现单例。
4.3 Vuex 数据缓存
// src/store.jslet Vue;export class Store {constructor(options {}) {if (!Vue typeof window ! undefined window.Vue) {install(window.Vue)}}
}export function install (_Vue) {if (Vue _Vue Vue) {if (__DEV__) {console.error([vuex] already installed. Vue.use(Vuex) should be called only once.)}return}Vue _VueapplyMixin(Vue)
}在上面代码中很明显可以找到一个单例模式的应用在Store的初始化时只会执行一次install方法。在install方法中会将Vue赋值并将vuex的相关逻辑绑定到Vue实例上。
4.4 antd/message
// components/messagelet messageInstance;function getMessageInstance(callback) {if (messageInstance) {callback(messageInstance);return;}Notification.newInstance({prefixCls,transitionName,style: { top: defaultTop }, // 覆盖原来的样式getContainer,maxCount,},instance {if (messageInstance) {callback(messageInstance);return;}messageInstance instance;callback(instance);},);
}在上面代码中我们可以看到当已经存在messageInstance时会直接复用对应的实例callback(messageInstance),否则的话将会赋值messageInstance instance。
先看下面这段代码
templatediva-button clickhandleMessagemessage/a-button/div
/templateexport default {methods: {handleMessage() {this.$message.info(handleMessage);},},created() {this.$message.config({top: 100px,duration: 1,});},
};这是一个vue组件在created时我们配置了message的参数当点击按钮时会执行方法调用message.info方法弹出组件。在message源码中会通过执行notice方法弹出弹窗而如果我们是第一次弹出弹窗时 会创建一个ant-message节点其中top: 100px就是刚才设置的配置项当我们再次触发时 可以看到会复用刚刚创建的dom节点并在内部创建一个弹窗。那么这样做有什么好处呢
最显然的一个优势就是复用了dom节点还有一个优势当我们连续多次点击时可以看到弹窗的效果是按顺序依次显示的只有一个dom节点可以保证多次弹出的弹窗只有一个父节点那么弹窗位置只要由父节点控制即可不需要每次都重新计算效果如图所示 4.5 axios取消重复请求
import axios from axios;
const CancelToken axios.CancelToken;
let cancelId 0;
let cancelArray [];// 添加请求拦截器
axios.interceptors.request.use(function (config) {// 在请求时可以添加自己的特点标识去筛选出需要重复取消的接口const source CancelToken.source();cancelId;const id cancelId;config.cancelId id;config.cancelToken source.token;const cancelIndex cancelArray.findIndex(e e.url config.url);cancelArray.push({id,url: config.url,source})if (cancelIndex -1) {cancelArray[cancelIndex].source.cancel(取消重复请求);cancelArray.splice(cancelIndex, 1)}return config;
}, function (error) {return Promise.reject(error);
});// 添加响应拦截器
axios.interceptors.response.use(function (response) {const cancelIndex cancelArray.findIndex(e e.id response.cancelId);if (cancelIndex -1) {cancelArray.splice(cancelIndex, 1)}// 对响应数据做点什么return response;
}, function (error) {if (axios.isCancel(error)) {// 如果是取消的接口可以自行返回一个特定标识console.log(isCancel)} else {// 对响应错误做点什么return Promise.reject(error);}
});export default axios5 策略模式
定义一系列算法把他们一个个封装起来并且使他们可以相互替换。
在平时的工作中也存在非常多应用场景比如业务中经常会存在针对不同场景执行不同逻辑的情况就可以考虑使用策略模式
5.1 JavaScript版本的策略模式
业务描述实现一个计算年终奖的功能绩效为S的人有4倍工资A为3倍工资B为2倍工资。
var strategies {S: function(salary) {return salary * 4;},A: function(salary) {return salary * 3;},B: function() {return salary * 2;}
}var calculateBouns function(level, salary) {return strategies[level](salary);
}calculateBouns(A, 2000);5.2 axios
axios既可用于浏览器中又可用于node环境中但通过源码可以得知在不同的环境将使用不同的方式发起请求
// lib/defaults.jsfunction getDefaultAdapter() {var adapter;if (typeof XMLHttpRequest ! undefined) {// For browsers use XHR adapteradapter require(./adapters/xhr);} else if (typeof process ! undefined Object.prototype.toString.call(process) [object process]) {// For node use HTTP adapteradapter require(./adapters/http);}return adapter;
}通过这段代码可以看到在axios中我们会根据环境赋值不同的adapter但XHR和Http发送请求的方式并不相同那么如何保证在不同场景使用方式相同呢其实axios会将不同的逻辑在各自内部处理最终暴露出相同的调用方式简单看下以下两部分代码:
// lib/adapters/xhr.jsmodule.exports function xhrAdapter(config) {return new Promise((resolve, reject) {/**省略xxxx代码*/var request new XMLHttpRequest();/**省略xxxx代码*/request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);})request.onreadystatechange function handleLoad() {/**省略xxxx代码*/// 对response进行校验满足条件则请求成功 resolve(response)settle(resolve, reject, response);}
}// lib/adapters/http.jsmodule.exports function httpAdapter(config) {return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {var resolve function resolve(value) {resolvePromise(value);};var reject function reject(value) {rejectPromise(value);};/**省略xxxx代码*/var transport;// 源码中有不同逻辑的判断这里简化为其中一种情况transport isHttpsProxy ? https : http;/**省略xxxx代码*/var req transport.request(options, function handleResponse(res) {/**省略xxxx代码*/res.on(end, function handleStreamEnd() {/**省略xxxx代码*/settle(resolve, reject, response);});})})
}两个都返回Promise,在不同的方法中各自处理了响应逻辑。在于使用时也就不需要再区分不同的环境了。
6 迭代器模式
提供一种方法顺序访问一个聚合对象中的各个元素而又不需要暴露该对象的内部表示。
迭代器模式可以把迭代的过程从业务逻辑中分离出来在使用迭代器模式之后即使不关心对象的内部构造也可以按顺序返回其中的每个元素。
6.1 JS中的迭代器
在JavaScript中相信大家经常听到过迭代、循环之类的名词把这两个概念区分一下
循环循环就是在满足一定条件时重复执行同一段代码典型的例子do...while迭代迭代是指按顺序逐个访问对象中的每一项典型的例子forEach
那么什么样的对象可以被迭代呢需要满足什么条件呢
要成为可迭代对象对象必须要实现必须实现iterator方法通常可以访问常量Symbol.iterator访问该属性。目前的内置可迭代对象有String、Array、TypedArray、Map、Set,他们的原型对象都实现了iterator方法。
当这个对象是可迭代对象时我们可以通过调用[Symbol.iterator]方法来按顺序遍历对象中的每一项
const arr [1, 2, 3, 4];
// 迭代器
const iterator arr[Symbol.iterator]()
iterator.next(); // { value: 1, done: false }
iterator.next(); // { value: 2, done: false }遍历比如forEach、for...of等方法其实就是封装了一个遍历可迭代对象的方法属于内部迭代器。而当我们通过调用next方法自行控制迭代对象遍历时比如ES6中的生成器函数这种就属于外部迭代器。
6.2 根据不同浏览器选择相应的上传组件
提供一个可以被迭代的方法使得getActiveUploadObj、getFlashUploadObj、getFormUploadObj依照优先级被迭代
我们会优先选择控件上传如果没有安装上传控件则使用Flash上传如果Flash也没有安装那就只好使用浏览器原生的表单上传了
// 定义各个上传方法
var getActiveUploadObj function() {try {return new ActiveXObject(TXFTNActiveX.FTNUpload);} cache(e) {return false}
}var getFlashUploadObj function() {if (supportFlash()) {var str object typeapplication/x-shockwave-flash/objectreturn $(str).appendTo($(body));}return false
}var getFormUploadObj function() {var str input namefile typefile / // 表单上传return $(str).appendTo($(body));
}// 按优先级迭代函数
var iteratorUploadObj function() {for (var i 0, fn; fn arguments[i];) {var uploadObj fn();if (uploadObj ! false) {return uploadObj}}
}// 获取可上传upload对象
var uploadObj iteratorUploadObj(getActiveUploadObj, getFlashUploadObj, getFormUploadObj)各个上传对象的方法互不干扰可以很好的维护和扩展代码。
7 代理模式
为一个对象提供一个代用品或占位符以便控制对它的访问。
代理模式的关键是当客户不方便直接访问一个对象或者不满足需要的时候提供一个替身对象来控制对这个对象的访问。客户实际上访问的是替身对象。替身对象对请求做出一些处理之后再把请求转交给本体对象。
保护代理和虚拟代理
代理B可以帮助A过滤掉一些请求比如送花的人中年龄太大的或者没有宝马的这种请求就可以直接在代理B处被拒绝掉这种代理叫做保护代理假设现实中花的价格不菲导致在程序世界里new Flower也是一个代价昂贵的操作那么我们可以把new Flower的操作交给代理B去执行代理B会选择在A心情好时在执行new Flower这种代理叫做虚拟代理虚拟代理把一些开销很大的对象延迟到真正需要它的时候才去创建。保护代理用于控制不同权限的对象对目标对象的访问。保护代理用于控制不同权限的对象对目标对象的访问而虚拟代理是最常用的一种代理模式。
7.1 虚拟代理合并HTTP请求
假设我们在做一个文件同步的功能当我们选中一个checkbox的时候它对应的文件就会被同步到另外一台服务器上面
var synchronousFile function (id) {console.log(开始同步文件, id)
}var proxySynchronousFile function() {var cache [],timer;return function(id) {cache.push(id);if (timer) {return;}timer settimeout(() {synchronousFile(cache.join(,));clearTimeout(timer);timer null;cache.length 0; // 清空id集合}, 2000)}
}()var checkbox document.getElementsByTagName(input)for (var i 0, c; c checkbox[i]) {c.onclick function() {if (this.checked true) {proxySynchronousFile(this.id);}}
}通过一个代理函数proxySynchronousFile来收集一段时间之内的请求最后一次性发给服务器如果不是实时性要求很高的系统有一点延迟并不会带来太大的副作用却能大大减轻服务器的压力
7.2 缓存代理
缓存代理可以为一些开销大的运算结果提供暂时的存储在下次运算时如果传递进来的参数跟之前的一致则可以直接返回前面的存储的运算结果。
var proxyMult (function() {var cache {};return function() {var args Array.prototype.join.call(arguments, ,);if (args in cache) {return cache[args];}return cache[args] mult.apply(this, arguments);}
})()proxyMult(1, 2, 3, 4) // 24
proxyMult(1, 2, 3, 4) // 24当第二次调用proxyMult(1, 2, 3, 4)时本体mult函数并没有被计算proxyMult直接返回了之前计算好的结果。通过增加缓存代理的方式mult函数可以继续专注于自身的职责——计算乘积缓存功能是由代理对象实现的。
7.3 Vue中的代理模式
当我们使用组件中的data、props和methods时只需要调用this.xxx即可拿initData的部分看下源码中是怎么处理的
// src/core/instance/state.jsfunction initData (vm: Component) {let data vm.$options.datadata vm._data typeof data function? getData(data, vm): data || {}if (!isPlainObject(data)) {data {}process.env.NODE_ENV ! production warn(data functions should return an object:\n https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function,vm)}// proxy data on instanceconst keys Object.keys(data)const props vm.$options.propsconst methods vm.$options.methodslet i keys.lengthwhile (i--) {const key keys[i]if (process.env.NODE_ENV ! production) {if (methods hasOwn(methods, key)) {warn(Method ${key} has already been defined as a data property.,vm)}}if (props hasOwn(props, key)) {process.env.NODE_ENV ! production warn(The data property ${key} is already declared as a prop. Use prop default value instead.,vm)} else if (!isReserved(key)) {proxy(vm, _data, key)}}// observe dataobserve(data, true /* asRootData */)
}可以看到首先我们设置了vm._data后面又执行了 proxy(vm, _data, key) 将vm._data.xxx代理到vm.xxx上,最后通过observe(data, true) 监听data的变化将data变为是响应式的。
所以要知道为什么可以直接使用this.xxx调用到组件中的data只需要了解proxy的实现即可 const sharedPropertyDefinition {enumerable: true,configurable: true,get: noop,set: noop
}export function proxy (target: Object, sourceKey: string, key: string) {sharedPropertyDefinition.get function proxyGetter () {return this[sourceKey][key]}sharedPropertyDefinition.set function proxySetter (val) {this[sourceKey][key] val}Object.defineProperty(target, key, sharedPropertyDefinition)
}可以看到通过修改get 和 set方法后当我们获取vm.xxx时实际则会取到this[sourceKey][key]也就是vm._data.xxx 。 文章转载自: http://www.morning.mhdwp.cn.gov.cn.mhdwp.cn http://www.morning.hmdn.cn.gov.cn.hmdn.cn http://www.morning.symgk.cn.gov.cn.symgk.cn http://www.morning.dnpft.cn.gov.cn.dnpft.cn http://www.morning.lfjmp.cn.gov.cn.lfjmp.cn http://www.morning.kclkb.cn.gov.cn.kclkb.cn http://www.morning.mdjzydr.com.gov.cn.mdjzydr.com http://www.morning.rcgzg.cn.gov.cn.rcgzg.cn http://www.morning.czcbl.cn.gov.cn.czcbl.cn http://www.morning.stprd.cn.gov.cn.stprd.cn http://www.morning.qtnmp.cn.gov.cn.qtnmp.cn http://www.morning.hsrpc.cn.gov.cn.hsrpc.cn http://www.morning.kkjhj.cn.gov.cn.kkjhj.cn http://www.morning.wpcfm.cn.gov.cn.wpcfm.cn http://www.morning.gjtdp.cn.gov.cn.gjtdp.cn http://www.morning.bhjyh.cn.gov.cn.bhjyh.cn http://www.morning.ppzgr.cn.gov.cn.ppzgr.cn http://www.morning.ywrt.cn.gov.cn.ywrt.cn http://www.morning.nlglm.cn.gov.cn.nlglm.cn http://www.morning.qdrhf.cn.gov.cn.qdrhf.cn http://www.morning.mdxwz.cn.gov.cn.mdxwz.cn http://www.morning.zmtrk.cn.gov.cn.zmtrk.cn http://www.morning.bchfp.cn.gov.cn.bchfp.cn http://www.morning.rwzkp.cn.gov.cn.rwzkp.cn http://www.morning.jjwzk.cn.gov.cn.jjwzk.cn http://www.morning.gkjnz.cn.gov.cn.gkjnz.cn http://www.morning.mpyry.cn.gov.cn.mpyry.cn http://www.morning.smdkk.cn.gov.cn.smdkk.cn http://www.morning.xlpdm.cn.gov.cn.xlpdm.cn http://www.morning.fjlsfs.com.gov.cn.fjlsfs.com http://www.morning.rqckh.cn.gov.cn.rqckh.cn http://www.morning.tsrg.cn.gov.cn.tsrg.cn http://www.morning.monstercide.com.gov.cn.monstercide.com http://www.morning.kghss.cn.gov.cn.kghss.cn http://www.morning.3jiax.cn.gov.cn.3jiax.cn http://www.morning.lmhwm.cn.gov.cn.lmhwm.cn http://www.morning.wsgyq.cn.gov.cn.wsgyq.cn http://www.morning.lrflh.cn.gov.cn.lrflh.cn http://www.morning.bwdnx.cn.gov.cn.bwdnx.cn http://www.morning.zmyhn.cn.gov.cn.zmyhn.cn http://www.morning.qbfs.cn.gov.cn.qbfs.cn http://www.morning.sqqdy.cn.gov.cn.sqqdy.cn http://www.morning.kynf.cn.gov.cn.kynf.cn http://www.morning.nafdmx.cn.gov.cn.nafdmx.cn http://www.morning.srkzd.cn.gov.cn.srkzd.cn http://www.morning.rcjwl.cn.gov.cn.rcjwl.cn http://www.morning.jpfpc.cn.gov.cn.jpfpc.cn http://www.morning.hdqqr.cn.gov.cn.hdqqr.cn http://www.morning.clwhf.cn.gov.cn.clwhf.cn http://www.morning.txzmy.cn.gov.cn.txzmy.cn http://www.morning.wxfjx.cn.gov.cn.wxfjx.cn http://www.morning.zcnfm.cn.gov.cn.zcnfm.cn http://www.morning.yxkyl.cn.gov.cn.yxkyl.cn http://www.morning.rgsgk.cn.gov.cn.rgsgk.cn http://www.morning.lxlfr.cn.gov.cn.lxlfr.cn http://www.morning.rbxsk.cn.gov.cn.rbxsk.cn http://www.morning.rgpy.cn.gov.cn.rgpy.cn http://www.morning.gwjqq.cn.gov.cn.gwjqq.cn http://www.morning.rjnm.cn.gov.cn.rjnm.cn http://www.morning.pbsfq.cn.gov.cn.pbsfq.cn http://www.morning.yfzld.cn.gov.cn.yfzld.cn http://www.morning.crrmg.cn.gov.cn.crrmg.cn http://www.morning.crfyr.cn.gov.cn.crfyr.cn http://www.morning.bnfrj.cn.gov.cn.bnfrj.cn http://www.morning.rxgnn.cn.gov.cn.rxgnn.cn http://www.morning.kgslc.cn.gov.cn.kgslc.cn http://www.morning.rpgdd.cn.gov.cn.rpgdd.cn http://www.morning.wmgjq.cn.gov.cn.wmgjq.cn http://www.morning.sqnrz.cn.gov.cn.sqnrz.cn http://www.morning.ghrlx.cn.gov.cn.ghrlx.cn http://www.morning.hfyll.cn.gov.cn.hfyll.cn http://www.morning.mprky.cn.gov.cn.mprky.cn http://www.morning.bmyrl.cn.gov.cn.bmyrl.cn http://www.morning.lxfyn.cn.gov.cn.lxfyn.cn http://www.morning.ykrss.cn.gov.cn.ykrss.cn http://www.morning.kfwqd.cn.gov.cn.kfwqd.cn http://www.morning.bqdgr.cn.gov.cn.bqdgr.cn http://www.morning.lmxzw.cn.gov.cn.lmxzw.cn http://www.morning.pzwfw.cn.gov.cn.pzwfw.cn http://www.morning.mcbqq.cn.gov.cn.mcbqq.cn