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

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

 更新時(shí)間:2020年04月19日 16:47:48   作者:China  
這篇文章主要介紹了vue2.x 對(duì)象劫持的原理實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(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;
  // 對(duì)象劫持 用戶改變了數(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ù)的層次過多 需要遞歸的去解析對(duì)象中的屬性,依次增加set和get方法
    // 對(duì)數(shù)組監(jiān)控
    this.walk(value); // 對(duì)對(duì)象進(jìn)行觀測(cè)
  }
  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)深度檢測(cè)
  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è)對(duì)象
      value = newValue;
    }
  });
}

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

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

/**
 * 
 * @param {*} data 當(dāng)前數(shù)據(jù)是不是對(duì)象
 */
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)深度檢測(cè)
  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è)對(duì)象
      value = newValue;
    }
  });
}

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

相關(guān)文章

  • Vue?element-ui?el-cascader?只能末級(jí)多選問題

    Vue?element-ui?el-cascader?只能末級(jí)多選問題

    這篇文章主要介紹了Vue?element-ui?el-cascader?只能末級(jí)多選問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 關(guān)于SpringBoot與Vue交互跨域問題解決方案

    關(guān)于SpringBoot與Vue交互跨域問題解決方案

    最近在利用springboot+vue整合開發(fā)一個(gè)前后端分離的個(gè)人博客網(wǎng)站,所以這一篇總結(jié)一下在開發(fā)中遇到的一個(gè)問題,關(guān)于解決在使用vue和springboot在開發(fā)前后端分離的項(xiàng)目時(shí),如何解決跨域問題。在這里分別分享兩種方法,分別在前端vue中解決和在后臺(tái)springboot中解決。
    2021-10-10
  • vue項(xiàng)目的html如何引進(jìn)public里面的js文件

    vue項(xiàng)目的html如何引進(jìn)public里面的js文件

    這篇文章主要介紹了vue項(xiàng)目的html如何引進(jìn)public里面的js文件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Vue實(shí)現(xiàn)極致舒適的可編輯表格

    Vue實(shí)現(xiàn)極致舒適的可編輯表格

    使用ElementPlus的Table啥都好,就是沒有可編輯表格,所以這篇文章就來和大家分享一下Vue實(shí)現(xiàn)極致舒適的可編輯表格的方法,希望對(duì)大家有所幫助
    2023-06-06
  • Vue圖片裁剪功能實(shí)現(xiàn)代碼

    Vue圖片裁剪功能實(shí)現(xiàn)代碼

    這篇文章主要介紹了Vue圖片裁剪功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • vue基于viewer實(shí)現(xiàn)的圖片查看器功能

    vue基于viewer實(shí)現(xiàn)的圖片查看器功能

    這篇文章主要介紹了vue基于viewer實(shí)現(xiàn)的圖片查看器的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-04-04
  • Vue下拉選擇框Select組件使用詳解(一)

    Vue下拉選擇框Select組件使用詳解(一)

    這篇文章主要為大家詳細(xì)介紹了Vue下拉選擇框Select組件的使用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vue中el-date-picker選擇日期的限制的項(xiàng)目實(shí)踐

    vue中el-date-picker選擇日期的限制的項(xiàng)目實(shí)踐

    ElementUI的el-date-picker使用時(shí),有時(shí)候想要限制用戶選擇的時(shí)間范圍,本文就來介紹了vue中el-date-picker選擇日期的限制的項(xiàng)目實(shí)踐,感興趣的可以了解一下
    2023-10-10
  • Vue CLI3 如何支持less的方法示例

    Vue CLI3 如何支持less的方法示例

    這篇文章主要介紹了Vue CLI3 如何支持less的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08
  • vue3項(xiàng)目中代碼出現(xiàn)紅色波浪線的問題及解決

    vue3項(xiàng)目中代碼出現(xiàn)紅色波浪線的問題及解決

    這篇文章主要介紹了vue3項(xiàng)目中代碼出現(xiàn)紅色波浪線的問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09

最新評(píng)論

丰原市| 芦溪县| 博罗县| 闽清县| 济源市| 济南市| 灵璧县| 奇台县| 开封市| 泽普县| 桃园县| 诸暨市| 太和县| 五台县| 永福县| 成安县| 郎溪县| 陵川县| 泰安市| 贺兰县| 左云县| 项城市| 平陆县| 工布江达县| 宁德市| 仙桃市| 历史| 新乡市| 彭水| 大名县| 九台市| 汶川县| 色达县| 赤壁市| 文昌市| 邵阳县| 荥经县| 安多县| 大港区| 榕江县| 西贡区|