最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從源碼角度帶你深入理解Vue依賴收集的核心

 更新時(shí)間:2026年03月02日 08:39:11   作者:會(huì)員源碼網(wǎng)  
在?Vue?的響應(yīng)式系統(tǒng)中,依賴收集是貫穿整個(gè)數(shù)據(jù)驅(qū)動(dòng)視圖的核心環(huán)節(jié),本文將從?Vue?2?的源碼出發(fā),層層拆解依賴收集的完整流程,帶你從?“使用層”?走向?“原理層”,真正理解?Vue?響應(yīng)式的底層邏輯

在 Vue 的響應(yīng)式系統(tǒng)中,“依賴收集” 是貫穿整個(gè)數(shù)據(jù)驅(qū)動(dòng)視圖的核心環(huán)節(jié)。很多開(kāi)發(fā)者日常使用datacomputed、watch時(shí)只知其然,卻不知其所以然 —— 為什么修改數(shù)據(jù)視圖會(huì)自動(dòng)更新?為什么computed能精準(zhǔn)緩存?這一切的背后,都是依賴收集機(jī)制在起作用。

本文將從 Vue 2 的源碼出發(fā),層層拆解依賴收集的完整流程,帶你從 “使用層” 走向 “原理層”,真正理解 Vue 響應(yīng)式的底層邏輯。

一、先搞懂:什么是 “依賴”

在開(kāi)始源碼分析前,我們先明確核心概念:

  • 依賴:本質(zhì)上是 “使用了某個(gè)響應(yīng)式數(shù)據(jù)的執(zhí)行函數(shù)”,比如渲染組件的render函數(shù)、computed的計(jì)算函數(shù)、watch的回調(diào)函數(shù)。
  • 依賴收集:在響應(yīng)式數(shù)據(jù)被讀取時(shí),記錄下 “哪些函數(shù)依賴了這個(gè)數(shù)據(jù)”;當(dāng)數(shù)據(jù)被修改時(shí),找到這些記錄的函數(shù)并執(zhí)行,最終實(shí)現(xiàn) “數(shù)據(jù)變 → 視圖更”。

簡(jiǎn)單來(lái)說(shuō),依賴收集的核心目標(biāo)是:建立 “響應(yīng)式數(shù)據(jù)” 與 “使用數(shù)據(jù)的函數(shù)” 之間的映射關(guān)系。

二、核心角色:依賴收集的 3 個(gè)關(guān)鍵模塊

Vue 2 的依賴收集主要依賴三個(gè)核心模塊,我們先認(rèn)識(shí)它們:

模塊作用核心源碼位置
Observer將普通對(duì)象 / 數(shù)組轉(zhuǎn)為響應(yīng)式(給屬性添加 get/set)src/core/observer/index.js
Dep依賴管理器:存儲(chǔ)某個(gè)響應(yīng)式數(shù)據(jù)的所有依賴src/core/observer/dep.js
Watcher依賴的載體:封裝需要執(zhí)行的函數(shù)(如 render、computed)src/core/observer/watcher.js

三者的關(guān)系可以總結(jié)為:

Observer 給數(shù)據(jù)加 get/set 鉤子 → 讀取數(shù)據(jù)時(shí)觸發(fā) get,通過(guò)Dep收集Watcher → 修改數(shù)據(jù)時(shí)觸發(fā) set,通過(guò)Dep通知所有Watcher執(zhí)行。

三、源碼拆解:依賴收集的完整流程

3.1 第一步:響應(yīng)式數(shù)據(jù)的初始化(Observer)

首先,Vue 會(huì)通過(guò)Observer類將data中的數(shù)據(jù)轉(zhuǎn)為響應(yīng)式,核心是給每個(gè)屬性定義getter/setter。

核心源碼(簡(jiǎn)化版):

// src/core/observer/index.js
class Observer {
  constructor(value) {
    this.value = value
    this.dep = new Dep() // 給對(duì)象/數(shù)組本身創(chuàng)建Dep
    def(value, '__ob__', this) // 給數(shù)據(jù)添加__ob__屬性,標(biāo)記為響應(yīng)式
    
    if (Array.isArray(value)) {
      // 處理數(shù)組的響應(yīng)式(重寫(xiě)push/pop等方法)
      this.observeArray(value)
    } else {
      // 處理對(duì)象的響應(yīng)式:遍歷屬性并定義get/set
      this.walk(value)
    }
  }

  // 遍歷對(duì)象屬性,定義響應(yīng)式
  walk(obj) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])
    }
  }

  // 遍歷數(shù)組,給每個(gè)元素做響應(yīng)式處理
  observeArray(items) {
    for (let i = 0, l = items.length; i < l; i++) {
      observe(items[i])
    }
  }
}

// 核心:給單個(gè)屬性定義get/set
export function defineReactive(
  obj,
  key,
  val,
  customSetter,
  shallow
) {
  // 每個(gè)響應(yīng)式屬性都有一個(gè)專屬的Dep實(shí)例
  const dep = new Dep()

  const property = Object.getOwnPropertyDescriptor(obj, key)
  if (property && property.configurable === false) {
    return
  }

  // 保留原有的get/set
  const getter = property && property.get
  const setter = property && property.set

  // 遞歸處理子屬性,保證深層數(shù)據(jù)也是響應(yīng)式
  let childOb = !shallow && observe(val)

  // 定義新的getter/setter
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    // 讀取屬性時(shí)觸發(fā):依賴收集的入口
    get: function reactiveGetter() {
      const value = getter ? getter.call(obj) : val
      
      // 關(guān)鍵:如果當(dāng)前有活躍的Watcher,就收集依賴
      if (Dep.target) {
        dep.depend() // 1. 讓Dep記錄當(dāng)前Watcher
        if (childOb) {
          // 2. 給對(duì)象/數(shù)組本身也收集依賴(處理數(shù)組/對(duì)象整體變更)
          childOb.dep.depend()
          if (Array.isArray(value)) {
            // 3. 數(shù)組特殊處理:遍歷子元素收集依賴
            dependArray(value)
          }
        }
      }
      return value
    },
    // 修改屬性時(shí)觸發(fā):通知依賴更新
    set: function reactiveSetter(newVal) {
      const value = getter ? getter.call(obj) : val
      // 新舊值相同則不處理
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      // 新值也要做響應(yīng)式處理
      childOb = !shallow && observe(newVal)
      // 關(guān)鍵:通知所有依賴更新
      dep.notify()
    }
  })
}

核心要點(diǎn)

  • 每個(gè)響應(yīng)式屬性都會(huì)創(chuàng)建一個(gè)Dep實(shí)例,專屬管理該屬性的依賴;
  • getter中觸發(fā)依賴收集,setter中觸發(fā)依賴更新;
  • 不僅處理單個(gè)屬性,還會(huì)遞歸處理子對(duì)象 / 數(shù)組,保證深層響應(yīng)式。

3.2 第二步:依賴管理器(Dep)

Dep是依賴的 “容器”,核心作用是存儲(chǔ)和管理某個(gè)數(shù)據(jù)的所有Watcher,提供depend(收集)和notify(通知)兩個(gè)核心方法。

核心源碼(簡(jiǎn)化版):

// src/core/observer/dep.js
export default class Dep {
  static target: ?Watcher; // 靜態(tài)屬性,存儲(chǔ)當(dāng)前活躍的Watcher
  id: number; // 唯一標(biāo)識(shí)
  subs: Array<Watcher>; // 存儲(chǔ)依賴的Watcher數(shù)組

  constructor() {
    this.id = uid++
    this.subs = []
  }

  // 添加一個(gè)Watcher到依賴列表
  addSub(sub: Watcher) {
    this.subs.push(sub)
  }

  // 移除一個(gè)Watcher
  removeSub(sub: Watcher) {
    remove(this.subs, sub)
  }

  // 核心:收集依賴(讓Dep和Watcher互相記錄)
  depend() {
    if (Dep.target) {
      // 調(diào)用當(dāng)前Watcher的addDep方法,雙向綁定
      Dep.target.addDep(this)
    }
  }

  // 核心:通知所有Watcher更新
  notify() {
    // 復(fù)制一份依賴列表,避免更新過(guò)程中列表變化
    const subs = this.subs.slice()
    for (let i = 0, l = subs.length; i < l; i++) {
      // 調(diào)用Watcher的update方法
      subs[i].update()
    }
  }
}

// 全局唯一的Dep.target棧(處理嵌套Watcher,比如computed嵌套)
Dep.target = null
const targetStack = []

// 入棧:設(shè)置當(dāng)前活躍的Watcher
export function pushTarget(target: ?Watcher) {
  targetStack.push(target)
  Dep.target = target
}

// 出棧:恢復(fù)上一個(gè)Watcher
export function popTarget() {
  targetStack.pop()
  Dep.target = targetStack[targetStack.length - 1]
}

核心要點(diǎn)

  • Dep.target是全局唯一的,始終指向 “當(dāng)前正在執(zhí)行的 Watcher”;
  • depend()方法不是直接添加 Watcher,而是調(diào)用Watcher.addDep(),實(shí)現(xiàn) Dep 和 Watcher 的雙向記錄(避免重復(fù)收集);
  • 用棧結(jié)構(gòu)targetStack處理嵌套場(chǎng)景(比如組件嵌套、computed 嵌套)。

3.3 第三步:依賴載體(Watcher)

Watcher是 “依賴” 的具體載體,每個(gè) Watcher 對(duì)應(yīng)一個(gè)需要執(zhí)行的函數(shù)(比如組件的render函數(shù)、computed的計(jì)算函數(shù))。

核心源碼(簡(jiǎn)化版):

// src/core/observer/watcher.js
export default class Watcher {
  constructor(
    vm: Component,
    expOrFn: string | Function,
    cb: Function,
    options?: ?Object,
    isRenderWatcher?: boolean
  ) {
    this.vm = vm
    if (isRenderWatcher) {
      vm._watcher = this
    }
    vm._watchers.push(this)
    
    // 處理配置項(xiàng)(比如lazy、deep、sync)
    if (options) {
      this.lazy = !!options.lazy // computed用
      this.deep = !!options.deep // 深度監(jiān)聽(tīng)用
      this.sync = !!options.sync // 同步更新用
    } else {
      this.lazy = this.deep = this.sync = false
    }
    
    this.cb = cb // 更新回調(diào)
    this.id = uid++ // 唯一標(biāo)識(shí)
    this.deps = [] // 存儲(chǔ)當(dāng)前Watcher依賴的Dep
    this.newDeps = [] // 臨時(shí)存儲(chǔ)新依賴(用于依賴清理)
    this.depIds = new Set() // 去重
    this.newDepIds = new Set()
    
    // 解析表達(dá)式/函數(shù),得到最終要執(zhí)行的函數(shù)
    this.getter = typeof expOrFn === 'function' ? expOrFn : parsePath(expOrFn)
    
    // 非lazy模式(比如render、watch)立即執(zhí)行g(shù)et,觸發(fā)依賴收集
    this.value = this.lazy ? undefined : this.get()
  }

  // 核心:執(zhí)行g(shù)etter并收集依賴
  get() {
    // 1. 將當(dāng)前Watcher入棧,設(shè)置為Dep.target
    pushTarget(this)
    let value
    const vm = this.vm
    try {
      // 2. 執(zhí)行g(shù)etter(比如render函數(shù)),觸發(fā)數(shù)據(jù)的getter
      // 此時(shí)數(shù)據(jù)的getter會(huì)檢測(cè)到Dep.target,從而收集當(dāng)前Watcher
      value = this.getter.call(vm, vm)
    } catch (e) {
      // 錯(cuò)誤處理
    } finally {
      // 3. 深度監(jiān)聽(tīng)處理
      if (this.deep) {
        traverse(value)
      }
      // 4. 出棧,恢復(fù)Dep.target
      popTarget()
      // 5. 清理無(wú)用的依賴
      this.cleanupDeps()
    }
    return value
  }

  // 核心:添加Dep到Watcher(與Dep.depend()配合)
  addDep(dep: Dep) {
    const id = dep.id
    // 避免重復(fù)收集
    if (!this.newDepIds.has(id)) {
      this.newDepIds.add(id)
      this.newDeps.push(dep)
      if (!this.depIds.has(id)) {
        // 讓Dep也記錄當(dāng)前Watcher
        dep.addSub(this)
      }
    }
  }

  // 清理無(wú)用依賴(比如數(shù)據(jù)從視圖中移除后,不再監(jiān)聽(tīng))
  cleanupDeps() {
    // 省略清理邏輯...
  }

  // 核心:響應(yīng)式數(shù)據(jù)更新時(shí),觸發(fā)Watcher更新
  update() {
    if (this.lazy) {
      // computed:標(biāo)記為臟值,下次訪問(wèn)時(shí)重新計(jì)算
      this.dirty = true
    } else if (this.sync) {
      // 同步更新:立即執(zhí)行run
      this.run()
    } else {
      // 異步更新(Vue默認(rèn)):加入隊(duì)列,批量更新
      queueWatcher(this)
    }
  }

  // 執(zhí)行g(shù)etter并觸發(fā)回調(diào)
  run() {
    const value = this.get()
    if (value !== this.value || this.deep) {
      const oldValue = this.value
      this.value = value
      // 執(zhí)行回調(diào)(比如watch的回調(diào)函數(shù))
      this.cb.call(this.vm, value, oldValue)
    }
  }

  // computed專用:計(jì)算并返回最新值
  evaluate() {
    this.value = this.get()
    this.dirty = false
  }

  // 重新收集依賴
  depend() {
    let i = this.deps.length
    while (i--) {
      this.deps[i].depend()
    }
  }
}

核心要點(diǎn)

Watcher.get()是觸發(fā)依賴收集的關(guān)鍵:先將自身設(shè)為Dep.target,再執(zhí)行getter(比如render函數(shù)),此時(shí)render中用到的所有響應(yīng)式數(shù)據(jù)都會(huì)觸發(fā)getter,從而收集當(dāng)前 Watcher;

不同類型的 Watcher 有不同的更新策略:

  • 渲染 Watcher(render):異步更新,加入隊(duì)列批量執(zhí)行;
  • 計(jì)算 Watcher(computed):懶更新(lazy: true),只有訪問(wèn)時(shí)才重新計(jì)算;
  • 偵聽(tīng) Watcher(watch):可配置同步 / 異步,支持深度監(jiān)聽(tīng)。

四、特殊場(chǎng)景的依賴處理

4.1 數(shù)組的依賴收集

數(shù)組的響應(yīng)式處理和對(duì)象不同(因?yàn)閿?shù)組的索引無(wú)法被Object.defineProperty攔截),Vue 重寫(xiě)了push、popsplice等 7 個(gè)數(shù)組方法,核心邏輯:

// src/core/observer/array.js
const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)

// 重寫(xiě)的7個(gè)方法
const methodsToPatch = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
]

methodsToPatch.forEach(function (method) {
  // 保留原方法
  const original = arrayProto[method]
  def(arrayMethods, method, function mutator(...args) {
    // 執(zhí)行原方法
    const result = original.apply(this, args)
    // 獲取數(shù)組的__ob__(Observer實(shí)例)
    const ob = this.__ob__
    // 處理新增元素(push/unshift/splice),轉(zhuǎn)為響應(yīng)式
    let inserted
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
    }
    if (inserted) ob.observeArray(inserted)
    // 關(guān)鍵:通知依賴更新
    ob.dep.notify()
    return result
  })
})

核心:數(shù)組的依賴收集在數(shù)組本身的__ob__.dep中,修改數(shù)組時(shí)調(diào)用ob.dep.notify()觸發(fā)更新。

4.2 computed 的依賴收集

computed的 Watcher 是 “懶 Watcher”(lazy: true),特點(diǎn):

  • 初始化時(shí)不立即執(zhí)行get,只有首次訪問(wèn)時(shí)才觸發(fā);
  • 依賴的數(shù)據(jù)更新時(shí),只標(biāo)記dirty: true,不立即重新計(jì)算;
  • 下次訪問(wèn)computed屬性時(shí),才重新計(jì)算并緩存結(jié)果。

核心邏輯:

// src/core/instance/state.js
function createComputedGetter(key) {
  return function computedGetter() {
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      if (watcher.dirty) {
        // 只有臟值時(shí)才重新計(jì)算
        watcher.evaluate()
      }
      // 收集渲染W(wǎng)atcher到computed的依賴中
      if (Dep.target) {
        watcher.depend()
      }
      return watcher.value
    }
  }
}

五、常見(jiàn)問(wèn)題與面試考點(diǎn)

為什么 Vue 不能檢測(cè)數(shù)組索引和長(zhǎng)度的變化

  • 數(shù)組索引的get/set雖然能被Object.defineProperty攔截,但考慮到性能成本(數(shù)組元素可能很多),Vue 放棄了這種方式;
  • 數(shù)組長(zhǎng)度的set也無(wú)法被有效攔截,且修改長(zhǎng)度的場(chǎng)景較少;
  • 解決方案:使用 Vue 提供的變異方法(push/splice 等)或Vue.set

為什么修改對(duì)象的新屬性視圖不更新

  • 因?yàn)閷?duì)象初始化時(shí),只有已定義的屬性被添加了get/set,新屬性沒(méi)有;
  • 解決方案:使用Vue.set(obj, key, value)this.$set,本質(zhì)是給新屬性添加get/set并觸發(fā)依賴更新。

依賴收集為什么要雙向記錄(Dep→Watcher 和 Watcher→Dep)

  • 避免重復(fù)收集:通過(guò)depIdsnewDepIds去重;
  • 方便依賴清理:組件銷毀時(shí),Watcher 可以遍歷自己的deps,從 Dep 中移除自身;
  • 支持依賴更新:Watcher 可以通過(guò)deps重新收集依賴(比如computeddepend方法)。

六、總結(jié)

Vue 的依賴收集機(jī)制是響應(yīng)式系統(tǒng)的靈魂,核心可以總結(jié)為 3 點(diǎn):

  • 核心鏈路Observer給數(shù)據(jù)加get/set → 讀取數(shù)據(jù)時(shí)Dep收集Watcher → 修改數(shù)據(jù)時(shí)Dep通知Watcher執(zhí)行 → 視圖更新;
  • 核心角色Observer(響應(yīng)式標(biāo)記)、Dep(依賴容器)、Watcher(依賴載體)三者協(xié)同工作;
  • 性能優(yōu)化:通過(guò)懶更新(computed)、異步隊(duì)列(渲染 Watcher)、依賴清理等方式,保證響應(yīng)式的高效性。

理解依賴收集,不僅能幫你解決日常開(kāi)發(fā)中的響應(yīng)式問(wèn)題,更能讓你從底層理解 Vue 的設(shè)計(jì)思想。

以上就是從源碼角度帶你深入理解Vue依賴收集的核心的詳細(xì)內(nèi)容,更多關(guān)于Vue依賴收集的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue如何動(dòng)態(tài)給img賦值

    vue如何動(dòng)態(tài)給img賦值

    這篇文章主要介紹了vue如何動(dòng)態(tài)給img賦值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 使用vue3+vite導(dǎo)入圖片路徑錯(cuò)亂問(wèn)題排查及解決

    使用vue3+vite導(dǎo)入圖片路徑錯(cuò)亂問(wèn)題排查及解決

    使用vue3+vite開(kāi)發(fā)的時(shí)候,導(dǎo)入svg圖片時(shí),同一個(gè)文件夾下的文件,其中一個(gè)路徑正常解析,另一個(gè)不行,更改文件名之后,該圖片文件就可以正常解析了,本文給大家介紹了使用vue3+vite導(dǎo)入圖片路徑錯(cuò)亂問(wèn)題排查及解決,需要的朋友可以參考下
    2024-03-03
  • vue引用public目錄下文件的方式詳解

    vue引用public目錄下文件的方式詳解

    由于一些演示需要對(duì)一些簡(jiǎn)單頁(yè)面進(jìn)行配置,由于打包build后的vue項(xiàng)目基本已經(jīng)看不出原樣,因此需要?jiǎng)?chuàng)建一個(gè)文件,并在打包的時(shí)候不會(huì)進(jìn)行編譯,所以文件放在public,下面這篇文章主要給大家介紹了關(guān)于vue引用public目錄下文件的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • Vue生命周期實(shí)例分析總結(jié)

    Vue生命周期實(shí)例分析總結(jié)

    Vue的生命周期就是vue實(shí)例從創(chuàng)建到銷毀的全過(guò)程,也就是new Vue()開(kāi)始就是vue生命周期的開(kāi)始。Vue實(shí)例有?個(gè)完整的?命周期,也就是從開(kāi)始創(chuàng)建、初始化數(shù)據(jù)、編譯模版、掛載Dom->渲染、更新->渲染、卸載等?系列過(guò)程,稱這是Vue的?命周期
    2022-10-10
  • 深入淺出分析vue2和vue3的區(qū)別

    深入淺出分析vue2和vue3的區(qū)別

    這篇文章主要介紹了vue2和vue3的區(qū)別,較為詳細(xì)的分析了vue2與vue3的常見(jiàn)區(qū)別與使用方法,需要的朋友可以參考下
    2023-06-06
  • Vue管理系統(tǒng)前端之組件拆分封裝詳解

    Vue管理系統(tǒng)前端之組件拆分封裝詳解

    這篇文章主要給大家介紹了關(guān)于Vue管理系統(tǒng)前端之組件拆分封裝的相關(guān)資料,文中通過(guò)實(shí)例代碼結(jié)束的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • VUE3之Non-Props屬性的具體使用

    VUE3之Non-Props屬性的具體使用

    本文主要介紹了VUE3之Non-Props屬性的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • vue element ui validate 主動(dòng)觸發(fā)錯(cuò)誤提示操作

    vue element ui validate 主動(dòng)觸發(fā)錯(cuò)誤提示操作

    這篇文章主要介紹了vue element ui validate 主動(dòng)觸發(fā)錯(cuò)誤提示操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • 使用Vite處理css?less及postcss示例詳解

    使用Vite處理css?less及postcss示例詳解

    這篇文章主要為大家介紹了使用Vite處理css?less及postcss的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Vue前端空值處理的實(shí)戰(zhàn)指南與避坑記錄

    Vue前端空值處理的實(shí)戰(zhàn)指南與避坑記錄

    本文旨在幫助同學(xué)們學(xué)會(huì)在前端真實(shí)業(yè)務(wù)項(xiàng)目里,到底該怎么寫(xiě)空值處理(?.、??、||、if判斷、兜底邏輯),以及為什么這么選、會(huì)踩哪些高頻坑,順便幫大家拉直JS/TS空值、真值假值的基礎(chǔ)概念,助力你們寫(xiě)出規(guī)范可維護(hù)的團(tuán)隊(duì)級(jí)代碼
    2026-03-03

最新評(píng)論

凤庆县| 津市市| 和田市| 长宁县| 巴马| 新竹市| 交口县| 昌黎县| 铜鼓县| 修武县| 奉化市| 额济纳旗| 东乡县| 金门县| 东乌珠穆沁旗| 临汾市| 清原| 礼泉县| 临沭县| 永平县| 兴国县| 石狮市| 红桥区| 荥阳市| 大兴区| 博兴县| 抚远县| 衡阳市| 花莲市| 胶州市| 忻城县| 山西省| 高要市| 杨浦区| 江口县| 新平| 确山县| 夏河县| 清流县| 威海市| 安乡县|