
长期招聘全职uniapp开发,主要为APP。月薪2W到3W。
长期招聘全职uniapp开发,主要为APP。月薪2W到3W。
**需远程连接进行开发,可个人,可签合同。
要求:
3年及以上开发经验
uniapp技术栈:必须熟练掌握以下 (npro和uview,nvue,sass,unicloud)
项目经验丰富,能够快速理解并上手他人项目,对项目进行继续开发。
时间充裕,工作态度认真,代码逻辑严谨**
有意者联系V:oyo476
有人监工,不适合划水。
长期招聘全职uniapp开发,主要为APP。月薪2W到3W。
**需远程连接进行开发,可个人,可签合同。
要求:
3年及以上开发经验
uniapp技术栈:必须熟练掌握以下 (npro和uview,nvue,sass,unicloud)
项目经验丰富,能够快速理解并上手他人项目,对项目进行继续开发。
时间充裕,工作态度认真,代码逻辑严谨**
有意者联系V:oyo476
有人监工,不适合划水。
收起阅读 »
发现一款可以生成uniapp项目代码的工具
http://wtm.plus
可以在线拖拽制作页面,能在线预览,并且可以下载完整的uniapp项目代码,可以直接用hbuilder打开运行的。
http://wtm.plus
可以在线拖拽制作页面,能在线预览,并且可以下载完整的uniapp项目代码,可以直接用hbuilder打开运行的。

nvue map 高德地图组件升级、离线个性化地图、离线设置样式文件、可使用nvue map 所有功能
nvue map 高德地图组件升级、离线个性化地图、离线设置样式文件、可使用nvue map 所有功能:https://ext.dcloud.net.cn/plugin?id=7637
nvue map 高德地图组件升级、离线个性化地图、离线设置样式文件、可使用nvue map 所有功能:https://ext.dcloud.net.cn/plugin?id=7637
收起阅读 »
【报Bug】uni.getSystemInfoSync().safeAreaInsets.bottom为 -48 的错误
【报Bug】uni.getSystemInfoSync().safeAreaInsets.bottom为 -48 的错误 Hbuilder v3.3.11
【报Bug】uni.getSystemInfoSync().safeAreaInsets.bottom为 -48 的错误 Hbuilder v3.3.11

android端实体返回键阻止返回上一页且实现点击两次退出
在页面中加入一下代码:
data() {
return {
backButtonPress: 0
}
}
......
onBackPress() {
this.backButtonPress ++
if (this.backButtonPress > 1) {
plus.runtime.quit()
} else {
plus.nativeUI.toast(this.$t('app.quit'))
}
setTimeout(() => {
this.backButtonPress = 0;
}, 2000)
return true
}
将backButtonPress设置为0的延时处理,设置为2000毫秒,为了和plus.nativeUI.toast默认的显示时长保持一致:
https://www.html5plus.org/doc/zh_cn/nativeui.html#plus.nativeUI.toast
https://www.html5plus.org/doc/zh_cn/nativeui.html#plus.nativeUI.ToastStyles
duration: (String 类型 )提示消息框显示的时间
可选值为"long"、"short",值为"long"时显示时间约为3.5s,值为"short"时显示时间约为2s,未设置时默认值为"short"。
在页面中加入一下代码:
data() {
return {
backButtonPress: 0
}
}
......
onBackPress() {
this.backButtonPress ++
if (this.backButtonPress > 1) {
plus.runtime.quit()
} else {
plus.nativeUI.toast(this.$t('app.quit'))
}
setTimeout(() => {
this.backButtonPress = 0;
}, 2000)
return true
}
将backButtonPress设置为0的延时处理,设置为2000毫秒,为了和plus.nativeUI.toast默认的显示时长保持一致:
https://www.html5plus.org/doc/zh_cn/nativeui.html#plus.nativeUI.toast
https://www.html5plus.org/doc/zh_cn/nativeui.html#plus.nativeUI.ToastStyles
duration: (String 类型 )提示消息框显示的时间
可选值为"long"、"short",值为"long"时显示时间约为3.5s,值为"short"时显示时间约为2s,未设置时默认值为"short"。

文件选择器、快速查询文件、自定义路径、完全自定义UI界面、可多选、自定义类型(android)
文件选择器、快速查询文件、自定义路径、完全自定义UI界面、可多选、自定义类型(android):https://ext.dcloud.net.cn/plugin?id=7608
文件选择器、快速查询文件、自定义路径、完全自定义UI界面、可多选、自定义类型(android):https://ext.dcloud.net.cn/plugin?id=7608
收起阅读 »
微信小程序源码+开源H5小游戏代码全套
微信小程序和小游戏源代码创建思路:
1.6万套微信小程序和小游戏源代码:casgams.top/gm
●创建一个数字猜测游戏,在其中用户选择一个范围;
●假设用户选择了一个范围,例如,从a到B,其中a和B属于Integer;
●系统将选择某个随机整数,用户必须在猜测的最小次数中猜测这个整数。
源码分析:
解释1:如果用户输入范围是1到100。编译器随机选择42作为整数。现在猜谜游戏开始了,所以用户输入50作为他/她的第一猜。编译器显示“Try Again!”你猜得太高了。”这意味着随机数(即42)不会落在50到100之间。这就是猜范围的一半的重要性。再一次,用户猜50的一半(你能告诉我为什么吗?)50的一半是25。用户输入25作为他/她的第二个猜测。这一次,编译器将显示“Try Again!”你猜的太小了。”这意味着小于25的整数(从1到25)是无法猜测的。现在用户猜测的范围更短了,即从25到50。智能!用户猜了这个范围的一半,所以,用户第三次猜37。这一次,编译器再次显示输出:“重试!”你猜的太小了。”对于用户来说,每猜一次,猜测范围就会变小。用户的猜测范围是37到50,用户的第四次猜测是43。这一次,编译器将显示“Try Again!”你猜得太高了。”因此,用户的猜测范围将从37到43,同样,用户猜测的是这个范围的一半,即40作为他/她的第五次猜测。这一次,编译器显示输出:“Try Again!”你猜的太小了。”让猜测更小,从41到43。现在用户第六次猜41。这是错误的,显示输出“Try Again!”你猜的太小了。”最后,用户第七次猜对了42。
总猜测次数= 7
解释2:如果用户输入范围是1到50。编译器随机选择42作为整数。现在猜谜游戏开始了。50的一半是25。用户输入25作为他/她的第一个猜测。这一次,编译器将显示“Try Again!”你猜的太小了。”这意味着小于25的整数(从1到25)是无法猜测的。现在用户猜测的范围更短了,即从25到50。智能!用户猜了这个范围的一半,所以,用户猜了37作为他/她的第二次猜测。这一次,编译器再次显示输出:“重试!”你猜的太小了。”对于用户来说,每猜一次,猜测范围就会变小。现在,用户的猜测范围是37到50,用户第三次猜43。这一次,编译器将显示“Try Again!”你猜得太高了。”因此,用户的猜测范围将从37到43,同样,用户猜测的是这个范围的一半,即40作为他/她的第四次猜测。这一次,编译器显示输出:“Try Again!”你猜的太小了。”让猜测更小,从41到43。现在用户第五次猜41。这是错误的,显示输出“Try Again!”你猜的太小了。”最后,用户第六次猜对了42。
总猜测次数= 6
所以,猜测的最小次数取决于范围。编译器必须计算出猜测的最小次数,这取决于范围本身。对于这个,我们有一个公式:
Minimum number of guessing = log2(Upper bound – lower bound + 1)
代码算法步骤如下:
●用户输入范围的上界和下界;
●编译器在范围之间生成一个随机整数,并将其存储在一个变量中,以备将来引用;
●为了进行重复猜测,将初始化一个while循环;
●如果用户猜测的数字大于随机选择的数字,用户将得到一个输出“重试!”你猜得太高了。”;
●如果用户猜测的数字小于随机选择的数字,用户将得到一个输出“Try Again!”你猜的太小了。”;
●如果用户猜了最少的次数,用户就会得到一个“恭喜!”输出;
●否则,如果用户没有在最小猜测次数中猜出整数,他/她将得到“Better Luck Next Time!””输出。
源码实现如下:
import random
import math
# Taking Inputs
lower = int(input("Enter Lower bound:- "))
# Taking Inputs
upper = int(input("Enter Upper bound:- "))
# generating random number between
# the lower and upper
x = random.randint(lower, upper)
print("\n\tYou've only ",
round(math.log(upper - lower + 1, 2)),
" chances to guess the integer!\n")
# Initializing the number of guesses.
count = 0
# for calculation of minimum number of
# guesses depends upon range
while count < math.log(upper - lower + 1, 2):
count += 1
# taking guessing number as input
guess = int(input("Guess a number:- "))
# Condition testing
if x == guess:
print("Congratulations you did it in ",
count, " try")
# Once guessed, loop will break
break
elif x > guess:
print("You guessed too small!")
elif x < guess:
print("You Guessed too high!")
# If Guessing is more than required guesses,
# shows this output.
if count >= math.log(upper - lower + 1, 2):
print("\nThe number is %d" % x)
print("\tBetter Luck Next time!")
# Better to use This source Code on pycharm!
下面是上面程序的输出结果:
微信小程序和小游戏源代码创建思路:
1.6万套微信小程序和小游戏源代码:casgams.top/gm
●创建一个数字猜测游戏,在其中用户选择一个范围;
●假设用户选择了一个范围,例如,从a到B,其中a和B属于Integer;
●系统将选择某个随机整数,用户必须在猜测的最小次数中猜测这个整数。
源码分析:
解释1:如果用户输入范围是1到100。编译器随机选择42作为整数。现在猜谜游戏开始了,所以用户输入50作为他/她的第一猜。编译器显示“Try Again!”你猜得太高了。”这意味着随机数(即42)不会落在50到100之间。这就是猜范围的一半的重要性。再一次,用户猜50的一半(你能告诉我为什么吗?)50的一半是25。用户输入25作为他/她的第二个猜测。这一次,编译器将显示“Try Again!”你猜的太小了。”这意味着小于25的整数(从1到25)是无法猜测的。现在用户猜测的范围更短了,即从25到50。智能!用户猜了这个范围的一半,所以,用户第三次猜37。这一次,编译器再次显示输出:“重试!”你猜的太小了。”对于用户来说,每猜一次,猜测范围就会变小。用户的猜测范围是37到50,用户的第四次猜测是43。这一次,编译器将显示“Try Again!”你猜得太高了。”因此,用户的猜测范围将从37到43,同样,用户猜测的是这个范围的一半,即40作为他/她的第五次猜测。这一次,编译器显示输出:“Try Again!”你猜的太小了。”让猜测更小,从41到43。现在用户第六次猜41。这是错误的,显示输出“Try Again!”你猜的太小了。”最后,用户第七次猜对了42。
总猜测次数= 7
解释2:如果用户输入范围是1到50。编译器随机选择42作为整数。现在猜谜游戏开始了。50的一半是25。用户输入25作为他/她的第一个猜测。这一次,编译器将显示“Try Again!”你猜的太小了。”这意味着小于25的整数(从1到25)是无法猜测的。现在用户猜测的范围更短了,即从25到50。智能!用户猜了这个范围的一半,所以,用户猜了37作为他/她的第二次猜测。这一次,编译器再次显示输出:“重试!”你猜的太小了。”对于用户来说,每猜一次,猜测范围就会变小。现在,用户的猜测范围是37到50,用户第三次猜43。这一次,编译器将显示“Try Again!”你猜得太高了。”因此,用户的猜测范围将从37到43,同样,用户猜测的是这个范围的一半,即40作为他/她的第四次猜测。这一次,编译器显示输出:“Try Again!”你猜的太小了。”让猜测更小,从41到43。现在用户第五次猜41。这是错误的,显示输出“Try Again!”你猜的太小了。”最后,用户第六次猜对了42。
总猜测次数= 6
所以,猜测的最小次数取决于范围。编译器必须计算出猜测的最小次数,这取决于范围本身。对于这个,我们有一个公式:
Minimum number of guessing = log2(Upper bound – lower bound + 1)
代码算法步骤如下:
●用户输入范围的上界和下界;
●编译器在范围之间生成一个随机整数,并将其存储在一个变量中,以备将来引用;
●为了进行重复猜测,将初始化一个while循环;
●如果用户猜测的数字大于随机选择的数字,用户将得到一个输出“重试!”你猜得太高了。”;
●如果用户猜测的数字小于随机选择的数字,用户将得到一个输出“Try Again!”你猜的太小了。”;
●如果用户猜了最少的次数,用户就会得到一个“恭喜!”输出;
●否则,如果用户没有在最小猜测次数中猜出整数,他/她将得到“Better Luck Next Time!””输出。
源码实现如下:
import random
import math
# Taking Inputs
lower = int(input("Enter Lower bound:- "))
# Taking Inputs
upper = int(input("Enter Upper bound:- "))
# generating random number between
# the lower and upper
x = random.randint(lower, upper)
print("\n\tYou've only ",
round(math.log(upper - lower + 1, 2)),
" chances to guess the integer!\n")
# Initializing the number of guesses.
count = 0
# for calculation of minimum number of
# guesses depends upon range
while count < math.log(upper - lower + 1, 2):
count += 1
# taking guessing number as input
guess = int(input("Guess a number:- "))
# Condition testing
if x == guess:
print("Congratulations you did it in ",
count, " try")
# Once guessed, loop will break
break
elif x > guess:
print("You guessed too small!")
elif x < guess:
print("You Guessed too high!")
# If Guessing is more than required guesses,
# shows this output.
if count >= math.log(upper - lower + 1, 2):
print("\nThe number is %d" % x)
print("\tBetter Luck Next time!")
# Better to use This source Code on pycharm!
下面是上面程序的输出结果:

一个完全 composition-api 的音频案例 vue3-audio
vue3-audio
一个完全由 composition-api 构建的音频播放案例。 具体可见 vue3-audio 完全 composition-api 的音频案例
主要用来演示 tob-use 中的 useAudio 的使用。
import { useAudio } from '@/uni_modules/tob-use'
// 播放列表
const playlist = ['src1', 'src2', '...']
const {
prev,
next,
toggle,
} = useAudio(playlist)
toggle() // 播放,开
toggle() // 暂停,关
toggle() // 播放,开
// ... 不断对当前状态取反
toggle(false) // 暂停
toggle(true) // 播放
toggle(true, 'new src') // 播放新的音频
prev() // 上一首
next() // 下一首
prev(2) // 上上首
next(2) // 下下首
vue3-audio
一个完全由 composition-api 构建的音频播放案例。 具体可见 vue3-audio 完全 composition-api 的音频案例
主要用来演示 tob-use 中的 useAudio 的使用。
import { useAudio } from '@/uni_modules/tob-use'
// 播放列表
const playlist = ['src1', 'src2', '...']
const {
prev,
next,
toggle,
} = useAudio(playlist)
toggle() // 播放,开
toggle() // 暂停,关
toggle() // 播放,开
// ... 不断对当前状态取反
toggle(false) // 暂停
toggle(true) // 播放
toggle(true, 'new src') // 播放新的音频
prev() // 上一首
next() // 下一首
prev(2) // 上上首
next(2) // 下下首
收起阅读 »

uniapp自定义组件父子组件props传递对象数据时,当对象中包含函数,子组件无法引用到对象中的函数的解决办法【转载】
uniapp自定义组件父子组件props传递对象数据时,当对象中包含函数,子组件无法引用到对象中的函数的解决办法
出现这种情况 是因为uniapp 在传递数据的时候使用的是JSON.parse(JSON.stringify(obj1))这样传递的 无法传递函数。
具体参考
[https://blog.csdn.net/py_boy/article/details/107089150]
解决办法是重写挂载在Vue原型对象上的patch方法 如下
import {myPatch} from "./extendWeixin"
// #ifndef H5
Vue.prototype.__patch__ = myPatch;
// #endif
extendWeixin.js 只需要把原来的patch方法复制过来稍微修改对象复制部分的代码即可
// replace platform patch function
const ARRAYTYPE = '[object Array]';
const OBJECTTYPE = '[object Object]';
export function myPatch (oldVnode, vnode) {
var this$1 = this;
if (vnode === null) { //destroy
return
}
if (this.mpType === 'page' || this.mpType === 'component') {
var mpInstance = this.$scope;
var data = Object.create(null);
try {
data = cloneWithData(this);
} catch (err) {
console.error(err);
}
data.__webviewId__ = mpInstance.data.__webviewId__;
var mpData = Object.create(null);
Object.keys(data).forEach(function (key) { //仅同步 data 中有的数据
mpData[key] = mpInstance.data[key];
});
var diffData = this.$shouldDiffData === false ? data : diff(data, mpData);
if (Object.keys(diffData).length) {
if (Object({
"NODE_ENV": "development",
"VUE_APP_NAME": "ancient-empire-app",
"VUE_APP_PLATFORM": "mp-weixin",
"BASE_URL": "/"
}).VUE_APP_DEBUG) {
console.log(
'[' + (+new Date) + '][' + (mpInstance.is || mpInstance.route)
+ '][' + this._uid +
']差量更新',
JSON.stringify(diffData));
}
this.__next_tick_pending = true;
mpInstance.setData(diffData, function () {
this$1.__next_tick_pending = false;
flushCallbacks$1(this$1);
});
} else {
flushCallbacks$1(this);
}
}
};
function cloneWithData(vm) {
// 确保当前 vm 所有数据被同步
var ret = Object.create(null);
var dataKeys = [].concat(
Object.keys(vm._data || {}),
Object.keys(vm._computedWatchers || {}));
dataKeys.reduce(function (ret, key) {
ret[key] = vm[key];
return ret
}, ret);
// vue-composition-api
var compositionApiState = vm.__composition_api_state__
|| vm.__secret_vfa_state__;
var rawBindings = compositionApiState && compositionApiState.rawBindings;
if (rawBindings) {
Object.keys(rawBindings).forEach(function (key) {
ret[key] = vm[key];
});
}
//TODO 需要把无用数据处理掉,比如 list=>l0 则 list 需要移除,否则多传输一份数据
Object.assign(ret, vm.$mp.data || {});
if (
Array.isArray(vm.$options.behaviors) &&
vm.$options.behaviors.indexOf('uni://form-field') !== -1
) { //form-field
ret['name'] = vm.name;
ret['value'] = vm.value;
}
return copyProperWithMethod(ret);
}
function diff(current, pre) {
var result = {};
syncKeys(current, pre);
_diff(current, pre, '', result);
return result
}
function syncKeys(current, pre) {
if (current === pre) {
return
}
var rootCurrentType = type(current);
var rootPreType = type(pre);
if (rootCurrentType == OBJECTTYPE && rootPreType == OBJECTTYPE) {
if (Object.keys(current).length >= Object.keys(pre).length) {
for (var key in pre) {
var currentValue = current[key];
if (currentValue === undefined) {
current[key] = null;
} else {
syncKeys(currentValue, pre[key]);
}
}
}
} else if (rootCurrentType == ARRAYTYPE && rootPreType == ARRAYTYPE) {
if (current.length >= pre.length) {
pre.forEach(function (item, index) {
syncKeys(current[index], item);
});
}
}
}
function flushCallbacks$1(vm) {
if (vm.__next_tick_callbacks && vm.__next_tick_callbacks.length) {
if (process.env.VUE_APP_DEBUG) {
var mpInstance = vm.$scope;
console.log(
'[' + (+new Date) + '][' + (mpInstance.is || mpInstance.route) + ']['
+ vm._uid +
']:flushCallbacks[' + vm.__next_tick_callbacks.length + ']');
}
var copies = vm.__next_tick_callbacks.slice(0);
vm.__next_tick_callbacks.length = 0;
for (var i = 0; i < copies.length; i++) {
copies[i]();
}
}
}
function _diff(current, pre, path, result) {
if (current === pre) {
return
}
var rootCurrentType = type(current);
var rootPreType = type(pre);
if (rootCurrentType == OBJECTTYPE) {
if (rootPreType != OBJECTTYPE || Object.keys(current).length < Object.keys(
pre).length) {
setResult(result, path, current);
} else {
var loop = function (key) {
var currentValue = current[key];
var preValue = pre[key];
var currentType = type(currentValue);
var preType = type(preValue);
if (currentType != ARRAYTYPE && currentType != OBJECTTYPE) {
if (currentValue != pre[key]) {
setResult(result, (path == '' ? '' : path + ".") + key,
currentValue);
}
} else if (currentType == ARRAYTYPE) {
if (preType != ARRAYTYPE) {
setResult(result, (path == '' ? '' : path + ".") + key,
currentValue);
} else {
if (currentValue.length < preValue.length) {
setResult(result, (path == '' ? '' : path + ".") + key,
currentValue);
} else {
currentValue.forEach(function (item, index) {
_diff(item, preValue[index],
(path == '' ? '' : path + ".") + key + '[' + index + ']',
result);
});
}
}
} else if (currentType == OBJECTTYPE) {
if (preType != OBJECTTYPE || Object.keys(currentValue).length
< Object.keys(preValue).length) {
setResult(result, (path == '' ? '' : path + ".") + key,
currentValue);
} else {
for (let subKey in currentValue) {
_diff(currentValue[subKey], preValue[subKey],
(path == '' ? '' : path + ".") + key + '.' + subKey, result);
}
}
}
};
for (var key in current) {
loop(key);
}
}
} else if (rootCurrentType == ARRAYTYPE) {
if (rootPreType != ARRAYTYPE) {
setResult(result, path, current);
} else {
if (current.length < pre.length) {
setResult(result, path, current);
} else {
current.forEach(function (item, index) {
_diff(item, pre[index], path + '[' + index + ']', result);
});
}
}
} else {
setResult(result, path, current);
}
}
function setResult(result, k, v) {
result[k] = v;
}
function type(obj) {
return Object.prototype.toString.call(obj)
}
function copyProperWithMethod(obj1){
let obj2 = JSON.parse(JSON.stringify(obj1));
copyMethodWithAddress(obj1, obj2);
return obj2;
}
function copyMethodWithAddress(from, to) {
let properArray = Object.keys(from);
for (let proper of properArray) {
let p = from[proper];
if (p instanceof Function) {
to[proper] = p;
} else if (p instanceof Array) {
if (!to[proper]) {
to[proper] = [];
}
copyMethodWithAddressByArray(p, to[proper]);
} else if (p instanceof Object) {
if (!to[proper]) {
to[proper] = {};
}
copyMethodWithAddress(p, to[proper])
}
}
}
function copyMethodWithAddressByArray(from, to) {
while (to.length < from.length) {
to.push(null);
}
for (let i = 0; i < from.length; i++) {
let a = from[i];
if (a instanceof Array){
copyMethodWithAddressByArray(a, to[i]);
} else if (a instanceof Function) {
to[i] = a;
} else if (a instanceof Object) {
copyMethodWithAddress(a, to[i]);
}
}
}
重点是 copyMethodWithAddress方法
原文链接:https://blog.csdn.net/qq_40445661/article/details/118539610
uniapp自定义组件父子组件props传递对象数据时,当对象中包含函数,子组件无法引用到对象中的函数的解决办法
出现这种情况 是因为uniapp 在传递数据的时候使用的是JSON.parse(JSON.stringify(obj1))这样传递的 无法传递函数。
具体参考
[https://blog.csdn.net/py_boy/article/details/107089150]
解决办法是重写挂载在Vue原型对象上的patch方法 如下
import {myPatch} from "./extendWeixin"
// #ifndef H5
Vue.prototype.__patch__ = myPatch;
// #endif
extendWeixin.js 只需要把原来的patch方法复制过来稍微修改对象复制部分的代码即可
// replace platform patch function
const ARRAYTYPE = '[object Array]';
const OBJECTTYPE = '[object Object]';
export function myPatch (oldVnode, vnode) {
var this$1 = this;
if (vnode === null) { //destroy
return
}
if (this.mpType === 'page' || this.mpType === 'component') {
var mpInstance = this.$scope;
var data = Object.create(null);
try {
data = cloneWithData(this);
} catch (err) {
console.error(err);
}
data.__webviewId__ = mpInstance.data.__webviewId__;
var mpData = Object.create(null);
Object.keys(data).forEach(function (key) { //仅同步 data 中有的数据
mpData[key] = mpInstance.data[key];
});
var diffData = this.$shouldDiffData === false ? data : diff(data, mpData);
if (Object.keys(diffData).length) {
if (Object({
"NODE_ENV": "development",
"VUE_APP_NAME": "ancient-empire-app",
"VUE_APP_PLATFORM": "mp-weixin",
"BASE_URL": "/"
}).VUE_APP_DEBUG) {
console.log(
'[' + (+new Date) + '][' + (mpInstance.is || mpInstance.route)
+ '][' + this._uid +
']差量更新',
JSON.stringify(diffData));
}
this.__next_tick_pending = true;
mpInstance.setData(diffData, function () {
this$1.__next_tick_pending = false;
flushCallbacks$1(this$1);
});
} else {
flushCallbacks$1(this);
}
}
};
function cloneWithData(vm) {
// 确保当前 vm 所有数据被同步
var ret = Object.create(null);
var dataKeys = [].concat(
Object.keys(vm._data || {}),
Object.keys(vm._computedWatchers || {}));
dataKeys.reduce(function (ret, key) {
ret[key] = vm[key];
return ret
}, ret);
// vue-composition-api
var compositionApiState = vm.__composition_api_state__
|| vm.__secret_vfa_state__;
var rawBindings = compositionApiState && compositionApiState.rawBindings;
if (rawBindings) {
Object.keys(rawBindings).forEach(function (key) {
ret[key] = vm[key];
});
}
//TODO 需要把无用数据处理掉,比如 list=>l0 则 list 需要移除,否则多传输一份数据
Object.assign(ret, vm.$mp.data || {});
if (
Array.isArray(vm.$options.behaviors) &&
vm.$options.behaviors.indexOf('uni://form-field') !== -1
) { //form-field
ret['name'] = vm.name;
ret['value'] = vm.value;
}
return copyProperWithMethod(ret);
}
function diff(current, pre) {
var result = {};
syncKeys(current, pre);
_diff(current, pre, '', result);
return result
}
function syncKeys(current, pre) {
if (current === pre) {
return
}
var rootCurrentType = type(current);
var rootPreType = type(pre);
if (rootCurrentType == OBJECTTYPE && rootPreType == OBJECTTYPE) {
if (Object.keys(current).length >= Object.keys(pre).length) {
for (var key in pre) {
var currentValue = current[key];
if (currentValue === undefined) {
current[key] = null;
} else {
syncKeys(currentValue, pre[key]);
}
}
}
} else if (rootCurrentType == ARRAYTYPE && rootPreType == ARRAYTYPE) {
if (current.length >= pre.length) {
pre.forEach(function (item, index) {
syncKeys(current[index], item);
});
}
}
}
function flushCallbacks$1(vm) {
if (vm.__next_tick_callbacks && vm.__next_tick_callbacks.length) {
if (process.env.VUE_APP_DEBUG) {
var mpInstance = vm.$scope;
console.log(
'[' + (+new Date) + '][' + (mpInstance.is || mpInstance.route) + ']['
+ vm._uid +
']:flushCallbacks[' + vm.__next_tick_callbacks.length + ']');
}
var copies = vm.__next_tick_callbacks.slice(0);
vm.__next_tick_callbacks.length = 0;
for (var i = 0; i < copies.length; i++) {
copies[i]();
}
}
}
function _diff(current, pre, path, result) {
if (current === pre) {
return
}
var rootCurrentType = type(current);
var rootPreType = type(pre);
if (rootCurrentType == OBJECTTYPE) {
if (rootPreType != OBJECTTYPE || Object.keys(current).length < Object.keys(
pre).length) {
setResult(result, path, current);
} else {
var loop = function (key) {
var currentValue = current[key];
var preValue = pre[key];
var currentType = type(currentValue);
var preType = type(preValue);
if (currentType != ARRAYTYPE && currentType != OBJECTTYPE) {
if (currentValue != pre[key]) {
setResult(result, (path == '' ? '' : path + ".") + key,
currentValue);
}
} else if (currentType == ARRAYTYPE) {
if (preType != ARRAYTYPE) {
setResult(result, (path == '' ? '' : path + ".") + key,
currentValue);
} else {
if (currentValue.length < preValue.length) {
setResult(result, (path == '' ? '' : path + ".") + key,
currentValue);
} else {
currentValue.forEach(function (item, index) {
_diff(item, preValue[index],
(path == '' ? '' : path + ".") + key + '[' + index + ']',
result);
});
}
}
} else if (currentType == OBJECTTYPE) {
if (preType != OBJECTTYPE || Object.keys(currentValue).length
< Object.keys(preValue).length) {
setResult(result, (path == '' ? '' : path + ".") + key,
currentValue);
} else {
for (let subKey in currentValue) {
_diff(currentValue[subKey], preValue[subKey],
(path == '' ? '' : path + ".") + key + '.' + subKey, result);
}
}
}
};
for (var key in current) {
loop(key);
}
}
} else if (rootCurrentType == ARRAYTYPE) {
if (rootPreType != ARRAYTYPE) {
setResult(result, path, current);
} else {
if (current.length < pre.length) {
setResult(result, path, current);
} else {
current.forEach(function (item, index) {
_diff(item, pre[index], path + '[' + index + ']', result);
});
}
}
} else {
setResult(result, path, current);
}
}
function setResult(result, k, v) {
result[k] = v;
}
function type(obj) {
return Object.prototype.toString.call(obj)
}
function copyProperWithMethod(obj1){
let obj2 = JSON.parse(JSON.stringify(obj1));
copyMethodWithAddress(obj1, obj2);
return obj2;
}
function copyMethodWithAddress(from, to) {
let properArray = Object.keys(from);
for (let proper of properArray) {
let p = from[proper];
if (p instanceof Function) {
to[proper] = p;
} else if (p instanceof Array) {
if (!to[proper]) {
to[proper] = [];
}
copyMethodWithAddressByArray(p, to[proper]);
} else if (p instanceof Object) {
if (!to[proper]) {
to[proper] = {};
}
copyMethodWithAddress(p, to[proper])
}
}
}
function copyMethodWithAddressByArray(from, to) {
while (to.length < from.length) {
to.push(null);
}
for (let i = 0; i < from.length; i++) {
let a = from[i];
if (a instanceof Array){
copyMethodWithAddressByArray(a, to[i]);
} else if (a instanceof Function) {
to[i] = a;
} else if (a instanceof Object) {
copyMethodWithAddress(a, to[i]);
}
}
}
重点是 copyMethodWithAddress方法
原文链接:https://blog.csdn.net/qq_40445661/article/details/118539610
收起阅读 »