欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue2.x 對象劫持的原理實(shí)現(xiàn)

 更新時(shí)間:2020年04月19日 16:47:48   作者:China  
這篇文章主要介紹了vue2.x 對象劫持的原理實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

目標(biāo):手寫迷你版Vue

一:使用rollup打包,打包后的代碼體積更小,更適合寫框架源碼的打包

npm i rollup -D

二:安裝babel相關(guān)的包,以及實(shí)現(xiàn)靜態(tài)服務(wù),設(shè)置環(huán)境變量的包

npm i @babel/core @babel/preset-env rollup-plugin-babel roullup-plugin-serve cross-env -D

三:包的相關(guān)介紹

  • rollup (打包工具)
  • @babel/core(用babel核心模塊)
  • @babel/preset-env(babel將高級(jí)語法轉(zhuǎn)成低級(jí)語法)
  • rollup-plugin-serve(實(shí)現(xiàn)靜態(tài)服務(wù))
  • cross-env(設(shè)置環(huán)境變量)
  • rollup-plugin-babel(橋梁)

四:根目錄書寫rollup.config.js

import babel from 'rollup-plugin-babel';
import serve from 'rollup-plugin-serve';
export default {
 input:'./src/index.js', // 以哪個(gè)文件作為打包的入口
 output:{
   file:'dist/umd/vue.js', // 出口路徑
   name:'Vue', // 指定打包后全局變量的名字
   format: 'umd', // 統(tǒng)一模塊規(guī)范
   sourcemap:true, // es6-> es5 開啟源碼調(diào)試 可以找到源代碼的報(bào)錯(cuò)位置
 },
 plugins:[ // 使用的插件
   babel({
     exclude:"node_modules/**"
   }),
   process.env.ENV === 'development'?serve({
     open:true,
     openPage:'/public/index.html', // 默認(rèn)打開html的路徑
     port:3000,
     contentBase:''
   }):null
 ]
}

配置package.josn

{
 "name": "vue_souce",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
  "build:dev": "rollup -c",
  "serve": "cross-env ENV=development rollup -c -w"
 },
 "keywords": [],
 "author": "",
 "license": "ISC",
 "devDependencies": {
  "@babel/core": "^7.9.0",
  "@babel/preset-env": "^7.9.5",
  "cross-env": "^7.0.2",
  "rollup": "^2.6.1",
  "rollup-plugin-babel": "^4.4.0",
  "rollup-plugin-serve": "^1.0.1"
 }
}

五:新建index.html(public/index.html)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="/dist/umd/vue.js"></script>
  <script>
    let vm = new Vue({
      el:'#app',
      // 隨便給些數(shù)據(jù)
      data(){
        return {
        name:'張三',
        age:11,
        address:{
          number:0,
          name:'李四'
        }}
      },
    })
    vm._data.address = {a:1};
    console.log(vm._data)
  </script>
</body>
</html>

六:編寫Vue入口:index.js

// Vue的核心代碼 只是Vue的一個(gè)聲明
import {initMixin} from './init';
function Vue(options){
  // 進(jìn)行Vue的初始化操作
  this._init(options);

}
// 通過引入文件的方式 給Vue原型上添加方法
initMixin(Vue); // 給Vue原型上添加一個(gè)_init方法
export default Vue

七:編寫初始化操作 init.js

import {initState} from './state'
// 在原型上添加一個(gè)init方法
export function initMixin(Vue){
  // 初始化流程
  Vue.prototype._init = function (options) {
    // 數(shù)據(jù)的劫持
    const vm = this; // vue中使用 this.$options 指代的就是用戶傳遞的屬性
    vm.$options = options;

    // 初始化狀態(tài)
    initState(vm); // 分割代碼
  }
}

八:初始化數(shù)據(jù)

import {observe} from './observer/index.js'
export function initState(vm){
  const opts = vm.$options;
  // vue的數(shù)據(jù)來源 屬性 方法 數(shù)據(jù) 計(jì)算屬性 watch
  if(opts.props){
    initProps(vm);
  }
  if(opts.methods){
    initMethod(vm);
  }
  if(opts.data){
    initData(vm);
  }
  if(opts.computed){
    initComputed(vm);
  }
  if(opts.watch){
    initWatch(vm);
  }
}
function initProps(){}
function initMethod() {}
function initData(vm){
  // 數(shù)據(jù)初始化工作
  let data = vm.$options.data; // 用戶傳遞的data
  data = vm._data = typeof data === 'function'?data.call(vm):data;
  // 對象劫持 用戶改變了數(shù)據(jù) 我希望可以得到通知 =》 刷新頁面
  // MVVM模式 數(shù)據(jù)變化可以驅(qū)動(dòng)視圖變化 
  // Object.defineProperty () 給屬性增加get方法和set方法
  observe(data); // 響應(yīng)式原理
}
function initComputed(){}
function initWatch(){}

九:書寫核心監(jiān)聽功能

// 把data中的數(shù)據(jù) 都使用Object.defineProperty重新定義 es5
// Object.defineProperty 不能兼容ie8 及以下 vue2 無法兼容ie8版本
import {
  isObject
} from '../util/index'
// 后續(xù)我可以知道它是不是一個(gè)已經(jīng)觀察了的數(shù)據(jù) __ob__
class Observer{
  constructor(value){ // 僅僅是初始化的操作
    // vue如果數(shù)據(jù)的層次過多 需要遞歸的去解析對象中的屬性,依次增加set和get方法
    // 對數(shù)組監(jiān)控
    this.walk(value); // 對對象進(jìn)行觀測
  }
  walk(data){
    let keys = Object.keys(data); // [name,age,address]

    // 如果這個(gè)data 不可配置 直接return
    keys.forEach((key)=>{
      defineReactive(data,key,data[key]);
    })
  }
}
function defineReactive(data,key,value){
  observe(value); // 遞歸實(shí)現(xiàn)深度檢測
  Object.defineProperty(data,key,{
    configurable:true,
    enumerable:false,
    get(){ // 獲取值的時(shí)候做一些操作
      return value;
    },
    set(newValue){ // 也可以做一些操作
      if(newValue === value) return;
      observe(newValue); // 繼續(xù)劫持用戶設(shè)置的值,因?yàn)橛锌赡苡脩粼O(shè)置的值是一個(gè)對象
      value = newValue;
    }
  });
}

export function observe(data) {
  let isObj = isObject(data);
  if (!isObj) {
    return
  }
  return new Observer(data); // 用來觀測數(shù)據(jù)
}

十:編寫工具類文件,存放校驗(yàn)對象

/**
 * 
 * @param {*} data 當(dāng)前數(shù)據(jù)是不是對象
 */
export function isObject(data) {
  return typeof data === 'object' && data !== null;
}

總結(jié):

1 創(chuàng)建Vue構(gòu)造函數(shù),接收所有所有參數(shù)options
2 分類初始化options,本章主要處理data,讓data上的引用類型的數(shù)據(jù)通過Object.definePrototy 變成響應(yīng)式的,初始化是有循序的,先初始化props 然后初始化method 然后初始化data computed watch

3 核心如下

function defineReactive(data,key,value){
  observe(value); // 遞歸實(shí)現(xiàn)深度檢測
  Object.defineProperty(data,key,{
    configurable:true,
    enumerable:false,
    get(){ // 獲取值的時(shí)候做一些操作
      return value;
    },
    set(newValue){ // 也可以做一些操作
      if(newValue === value) return;
      observe(newValue); // 繼續(xù)劫持用戶設(shè)置的值,因?yàn)橛锌赡苡脩粼O(shè)置的值是一個(gè)對象
      value = newValue;
    }
  });
}

到此這篇關(guān)于vue2.x 對象劫持的原理實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)vue2.x 對象劫持內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue切換菜單取消未完成接口請求的案例

    vue切換菜單取消未完成接口請求的案例

    這篇文章主要介紹了vue切換菜單取消未完成接口請求的案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue實(shí)現(xiàn)城市列表選擇功能

    vue實(shí)現(xiàn)城市列表選擇功能

    這篇文章主要介紹了vue實(shí)現(xiàn)城市列表選擇功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-07-07
  • Vue的diff算法原理你真的了解嗎

    Vue的diff算法原理你真的了解嗎

    這篇文章主要為大家詳細(xì)介紹了Vue的diff算法原理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • vue 組件間的通信之子組件向父組件傳值的方式

    vue 組件間的通信之子組件向父組件傳值的方式

    這篇文章主要介紹了vue 組件間的通信之子組件向父組件傳值的方式總結(jié),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • VUE實(shí)現(xiàn)圖片驗(yàn)證碼功能

    VUE實(shí)現(xiàn)圖片驗(yàn)證碼功能

    這篇文章主要為大家詳細(xì)介紹了VUE實(shí)現(xiàn)圖片驗(yàn)證碼功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • VUE+Element-ui實(shí)戰(zhàn)之使用el-calendar日歷自定義顯示內(nèi)容

    VUE+Element-ui實(shí)戰(zhàn)之使用el-calendar日歷自定義顯示內(nèi)容

    這篇文章主要介紹了VUE+Element-ui實(shí)戰(zhàn)之使用el-calendar日歷自定義顯示內(nèi)容方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Vue 3.0自定義指令的使用入門

    Vue 3.0自定義指令的使用入門

    在 Vue 的項(xiàng)目中,我們經(jīng)常會(huì)遇到 v-if、v-show、v-for 或 v-model 這些內(nèi)置指令,它們?yōu)槲覀兲峁┝瞬煌墓δ?。除了使用這些內(nèi)置指令之外,Vue 也允許注冊自定義指令。接下來,將使用Vue 3官方文檔自定義指令章節(jié)中使用的示例,來一步步揭開自定義指令背后的秘密。
    2021-05-05
  • vue.js高德地圖實(shí)現(xiàn)熱點(diǎn)圖代碼實(shí)例

    vue.js高德地圖實(shí)現(xiàn)熱點(diǎn)圖代碼實(shí)例

    這篇文章主要介紹了vue.js高德地圖實(shí)現(xiàn)熱點(diǎn)圖,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 詳解從vue-loader源碼分析CSS Scoped的實(shí)現(xiàn)

    詳解從vue-loader源碼分析CSS Scoped的實(shí)現(xiàn)

    這篇文章主要介紹了詳解從vue-loader源碼分析CSS Scoped的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Vue3 之 Vue 事件處理指南

    Vue3 之 Vue 事件處理指南

    Vue事件處理是每個(gè)Vue項(xiàng)目的必要方面。 它用于捕獲用戶輸入,共享數(shù)據(jù)以及許多其他創(chuàng)造性方式。在本文中,會(huì)介紹基礎(chǔ)知識(shí),并提供一些用于處理事件的代碼示例。需要的小伙伴可以參考下面文章的具體內(nèi)容
    2021-09-09

最新評論