rollup的环境配置
1. rolllup搭建环境
1.1 安装rollup
npm init
npm install @babel/preset-env @babel/core rollup rollup-plugin-babel rollup-plugin-serve -D
1.2 新建rollup.config.js 配置文件
import babel from 'rollup-plugin-babel'
import serve from 'rollup-plugin-serve'
export default {
input: './src/index.js', // 打包入口(在对应的位置添加文件)
output: {
file: 'dist/vue.js',
format: 'umd', // 在window 上 Vue new Vue
name: 'Vue',
sourcemap: true, // 转换前后的代码进行映射
},
plugin: [
babel({
exclude: 'node_modules/**', // 排除文件
}),
serve({
port: 3000,
contentBase: '', // 空字符表示当前目录
openPage: '/index.html'
})
]
}
1.3 创建babelrc 文件,配置babel
{
"presets": [
"@/babel/preset-env"
]
}
1.4 在package.json 文件中的script,添加脚本
"dev": "rollup -c -w", // -c 执行rollup.config.js; -w 代码的检测更新
1.5 使用npm run dev 注意: Cannot use import statement outside a module 则需要在package.json添加属性
"type": "module"
2. vue响应式
2.1 初始化Vue
2.1.1 创建Vue
function Vue(options) {
console.log('配置项:', options);
}
export default Vue
2.1.2 往Vue的prototype添加_init初始化参数
export function initMixin(Vue) {
Vue.prototype._init = function (options) {
console.log('初始化:', options);
}
}
2.1.3 在index.js中导入初始化的方法
import { initMixin } from './init.js'
function Vue(options) {
// console.log('配置项:', options);
this._init(options)
}
initMixin(Vue)
export default Vue
2.2.1 实现对data中对象的属性进行劫持
对象属性劫持通过Object.defineProperty()进行劫持 Object.defineProperty() 有缺点,只能劫持对象的一个属性 Vue中对对象进行劫持的步骤 1、Object.defineProperty() 缺点: 只能对对象中的一个而属性进行劫持
function defineReactive(data, key, value) {
Object.defineProperty(data, key, {
get() {
console.log('获取');
return value
},
set(newVal) {
if(newVal === value) return
Observe(newVal) // 值是对象,要进行递归
console.log('设置');
value = newVal
}
})
}
2、循环
class Observer{
constructor(value){
if(Array.isArray(value)) {
value.__proto__ = ArrayMethods
console.log('数组');
} else {
this.walk(value)
}
}
walk(data) {
let keys = Object.keys(data)
for(let i=0; keys.length > i; i ++ ) {
let key = keys[i]
let value = data[key]
defineReactive(data, key, value)
}
}
}
3、递归
function defineReactive(data, key, value) {
// 递归
Observe(value) // 深度代理
Object.defineProperty(data, key, {
get() {
console.log('获取');
return value
},
set(newVal) {
if(newVal === value) return
Observe(newVal) // 值是对象,要进行递归
console.log('设置');
value = newVal
}
})
}
2.2.1 对数组进行劫持
方法函数劫持,劫持数组方法
// 重写数组
// 1、获取原数组方法
let oldArrayProtoMethods = Array.prototype
// 2、继承
export let ArrayMethods = Object.create(oldArrayProtoMethods)
// 劫持
let methods = ['pop', 'push', 'shift', 'unshift', 'slice', 'splice']
methods.forEach( item => {
ArrayMethods[item] = function(...args) {
console.log('劫持数组方法:',item);
let result = oldArrayProtoMethods[item].apply(this, args)
return result
}
})
2.2.2 往数组添加属性
1、现在Observer定义好一个__ob__属性,该属性的value值为Observer的上下文
Object.defineProperty(value, "__ob__", {
enumerable: false,
value: this
})
2、在劫持的数组方法中,调用Observer的observeArray方法,对新添加的属性进行数据劫持
// 重写数组
// 1、获取原数组方法
let oldArrayProtoMethods = Array.prototype
// 2、继承
export let ArrayMethods = Object.create(oldArrayProtoMethods)
// 劫持
let methods = ['pop', 'push', 'shift', 'unshift', 'slice', 'splice']
methods.forEach( item => {
ArrayMethods[item] = function(...args) {
console.log('劫持数组方法:',item, args);
let result = oldArrayProtoMethods[item].apply(this, args)
let inserted = ''
switch(item) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.splice(2)
break
}
let ob = this.__ob__ // Observer
if(inserted) {
ob.observeArray(inserted)
}
return result
}
})
2.3 将data上的所有属性代理到实例上
function proxy(vm, source, key ) {
Object.defineProperty(vm[source], key, {
get() {
return vm[source][key]
},
set(newVal) {
vm[source][key] = newVal
}
})
}