百度怎么回答问题任务 随便回答个

需求发布后1小时内收到服务商响应每个需求平均有10个服务商参与95%以上的需求得到了圆满解决所有需求不向雇主收取任何佣金引爆店铺流量,提升网店销量
百度钱包任务,5元一个。在线秒审!
有相似问题想解决?专业顾问来帮助您
匹配服务商
选择服务商,签单
服务商工作
验收工作,满意后付款
参与报价,开始赚钱
提交你的报价和方案
中标后交付作品
获得任务赏金
急速:10分钟急速响应
省心:标准化服务
放心:不满意全额退款(免单)
品牌整合营销
口碑营销&推广
新闻稿发布题主想尝试完成一个mvvm表单小框架。但是由于现有的题目描述感觉细节还是太少了,题主还是不太明白任务是想达成一个怎样的效果。任务描述在此:其实本人对mvvm在表单上的实现也抱有很多困惑,先谈谈题主对这个框架的一些想法,核心的define是将对应input的validate进行注册(这里有个困惑就是不需要把对应的dom也注册么?这里实现的时候没有提到要在html中加入自己定义的模板什么的(eg. 再增加一个 el: "#username"这样的属性))个人对框架执行时的猜想:首先用户就在表单中输入信息,viewmodel中通过mutation observer监听input的attributes的改变来触发validate事件,这里也需要处理多种不同类型的validate函数类型,同时在validate里面的还会涉及到通过this对其他input进行操作的。(这里也有个困惑就是:这个过程也是属于mvvm中的双向数据绑定么?感觉只是一个观察者的模型呀)而且这个验证表单的实现感觉也没有出现model,感觉操作都是在view和viewmodel 上面进行的。当然以上只是个人的小小想法,题主对mvvm仍然不是十分的明白,对题意和mvvm的实现理解可能会有偏颇的地方。希望大神们可以就自己对mvvm的理解和想法对这个表单的具体实现给出一点点建议,谢谢QAQ
一、什么是MVVM?MVVM框架的核心不是双向绑定,也不是依赖收集或者脏检测,其核心思想可以表示为:View = F(...States)
即视图是状态的函数,如果我们把所有的状态都记录到同一个对象里面(比如叫Model),然后给这个F函数起个名字叫ViewModel,那么公式就变成了View = ViewModel(Model),就是所谓的MVVM了。通俗来讲,只要我们有一个JS的对象Model,修改它页面就跟着改(Model -& View的单向绑定),并且满足Model相同页面就相同,这个框架就是一个MVVM的框架了,所以说这一年来一直很流行的React也是一个MVVM框架。或者我们用代码来表达一下:var tpl = '&p&这是一个任何模板引擎都可以用的模板:姓名:${name}&/p&';
var model = {
name: '张三'
var container = document.getElementById('container');
model = new ViewModel(container, model, tpl);
function ViewModel(elem, model, tpl) {
var engine = new Engine(tpl);
var vm = observer(model).on('change', function () {
update(elem, engine.render(model));
return vm;
大家可以仔细看看不同MVVM框架的API定义,是不是都需要给出容器(container)、模型数据(model )和模板(tpl)三个核心元素呢。它们之间的不同之处在于两点:1、update不同:最早的一些框架中,大家使用的是字符串模板,好处在于模板书写起来简单,缺点嘛很明显,字符串是不能进行对比的,因此只能全量更新elem元素了,性能差而且会有明显的抖动。后来MVVM框架倾向于使用基于DOM的模板,这种模板的好处在于可以准确的定位到树上的任何一个元素,因此如果你能准确的知道Model中的哪个数据变化了,就能准确的知道我要修改哪个元素,可以以最小代价更新elem元素。问题也比较明显,我们需要把原来写在字符串模板中的各种指令,写到真实的DOM元素上去,于是种种奇葩的写法如:注释、自定义属性、插值、自定义元素都出来了,学习一个MVVM完全就是学习一门语言。React使用的是基于AST的模板引擎,算是一种兼顾前两者优点的解决方案,所以才会很留下,然而这也不是没有问题的,手写AST是相当反人类的,如果不手写你就要引入一个超过15000行的字符串模板 -& AST模板的翻译软件,这比DOM模板使用元素innerHTML就能翻译可大多了,好在我们可以用nodejs翻译了在网页中跑。2、observer不同:我们都知道MVVM的核心是当Model发生改变时,修改View,刚才我们分析了如何修改View,另外一个不同之处在于如果监控Model的变化。最简单的办法是使用函数,比如我们可以写下边这样的代码:function observer(model) {
var obj = {};
obj.on = function (type, fn) {
obj[type] = fn;
return model;
obj.emit = function (type) {
obj[type]();
model.$set = function (value) {
merge(model, value);
obj.emit('change');
return obj;
model.$set({
name: '李四'
不要觉得意外,最早的MVVM框架就是这么实现的,可能现在已经没有人这么用了吧。好的框架总是懒人发明的,当某个人写$set写到烦躁的时候,他会憧憬下边的写法:model.name = '李四';
这样看起来又清新,又自然还舒服。但是这有一个问题,在JS中简单的变量赋值是不会引发任何事件的,不过解决起来并不困难,比如这样:function observer(model){
var obj = {};
obj.on = function (type, fn) {
obj[type] = fn;
return proxy;
obj.emit = function (type) {
obj[type]();
var proxy = new Proxy(model, {
get: function (target, key, receiver) {
return Reflect.get(target, key, receiver);
set: function (target, key, value, receiver) {
Reflect.set(target, key, value, receiver);
obj.emit('change');
return obj;
以上方法好像没什么浏览器支持,但这确实是未来可以用的方法,类似的还有人想到了下边的办法:function observer(model){
var obj = {};
obj.on = function (type, fn) {
obj[type] = fn;
return proxy;
obj.emit = function (type) {
obj[type]();
var properties = {};
for(var x in model) {
properties[x] = {
get: function () {
return model[x];
set:function (value) {
model[x] = value;
obj.emit('change');
var proxy = Object.create({}, properties);
return obj;
这个办法的兼容性就好多了,IE9+都可以支持,不过仍然有人不满足于这个办法,因为Object.create函数支持程度有限嘛,不过这都不是事,IE678不是有VB嘛,我们可以用VB来模拟一个,比如这样:const defineProperties = (function () {
* 用于生成一个随机前缀,以防止重复
* @type {number}
let prefix = expando('vb');
* 属性组定义函数
* @type {Function}
let defineProperties = null;
// IE8只能给DOM元素定义属性
Object.defineProperty({}, '_', {
value: 'x'
defineProperties = Object.defineProperties;
catch (e) {
// IE6-8使用VB来模拟defineProperties
if (!defineProperties && window.VBArray) {
window.execScript([
// 执行VB字符串的函数
'Function parseVB(code)',
ExecuteGlobal(code)',
'End Function'
].join('\r\n'), 'VBScript');
* 用于存储定义过的类
* @type {Object}
let VBModelPool = {};
* VB回调JS的函数代理
* @param {Object} instance this对象
* @param {Object} accessors 回调的执行函数集合
* @param {string} name 属性名
* @param {*} [value] 属性值,不传递表示获取
* @return {*} 返回执行结果
let VBMediator = function (instance, accessors, name, value) {
var accessor = accessors[name];
// 设置模式
if (arguments.length === 4) {
// 可写属性处理
if (accessor.writable) {
accessor.value = value;
// setter处理
else if (accessor.set) {
accessor.set.call(instance, value);
// getter 处理
else if (accessor.get) {
return accessor.get.call(instance);
// 其它情况直接返回值
return accessor.value;
defineProperties = function (_, accessors) {
// 如果accessors不传,丢出一个错误
if (accessors == null) {
throw new TypeError('Cannot convert undefined or null to object');
// 生成类代码
let buffer = [];
buffer.push(
// 添加私有变量(__data__用于保存访问器,__proxy__用于代理执行JS函数)
Private [__data__], [__proxy__]',
// 定义构造函数
Public Default Function [__const__] (d, p)',
Set [__data__] = d',
Set [__proxy__] = p',
Set [__const__] = Me',
End Function'
// 添加访问器属性
each(accessors, name =& {
buffer.push(
// 添加LET方法(IE67使用LET方法)
Public Property Let [${name}](val` + prefix + `)`,
Call [__proxy__](Me, [__data__], "${name}", val${prefix})`,
End Property`,
// 添加SET方法(IE8使用SET方法)
Public Property Set [${name}](val${prefix})`,
Call [__proxy__](Me, [__data__], "${name}", val${prefix})`,
End Property`,
// 添加获取方法
Public Property Get [${name}]`,
On Error Resume Next`,
Set [${name}] = [__proxy__](Me, [__data__],"${name}")`,
If Err.Number && 0 Then`,
[${name}] = [__proxy__](Me, [__data__],"${name}")`,
On Error Goto 0`,
End Property`
let code = buffer.join('\r\n');
// 生成一个唯一的类名
let className = VBModelPool[code];
if (!className) {
className = VBModelPool[code] = 'VBClass' + guid(prefix);
buffer.unshift('Class ' + className);
// 添加类定义结束
buffer.push('End Class');
// 添加工厂类函数
buffer.push(
'Function ' + className + 'Factory(a, b)',
Set o = (New ' + className + ')(a, b)',
Set ' + className + 'Factory = o',
'End Function'
window.parseVB(buffer.join('\r\n'));
// 得到其产品
return window[className + 'Factory'](accessors, VBMediator);
return defineProperties;
于是IE678的问题就解决了,或者你觉得VB太反人类了,那就兼容到IE9+就好了嘛。不过这种办法只能针对对象,如果你要操作的东西是一个数组,你就没办法了,我们不可能给数组中的每一个项目都定义成属性吧,所以这类解决方案通常是在数组上使用$set函数,在对象上使用依赖收集,同时把数组的splice、push、pop、reverse、shift、unshift函数重载一下,进行监控。依赖收集虽好,但是数组对象区别对待太反人类了,于是就有了脏检测(这办法是先出来的),其原理就更简单了,起一个定时器,顺便diff一下model和model-backup就可以了。但是这种办法的性能是有问题的,所以更多的框架并没有选择这个对用户更友好的方法。二、双向绑定双向绑定不是MVVM所必须的,只是因为它很有用,所有大部分MVVM框架都实现了,那么什么是双向绑定呢,我们来考虑下边的情况:现在我们为模型添加一个价格函数,当用户名为张三时,返回10,不然返回5,姓名通过一个输入框输入。用代码实现起来并不复杂是吧,我们可以写成这样:model.price = function () {
if(model.name === '张三') {
return 10;
但这实际上是行不通的,因为name是通过输入框输入的,除了我们的ViewModel可以修改它,用户也是可以修改的。而双向绑定就是为了实现这个的。即:将用户的输入反馈到Model上,并触发View的一系列其它改变。为了实现这一效果,我们来更改一下我们的ViewModel函数:function ViewModel(elem, model, tpl) {
var engine = new Engine(tpl);
var vm = observer(model).on('change', function () {
update(elem, engine.render(model));
delegate(elem, function (type, name, value){
vm[name] = value;
return vm;
几乎所有的MVVM框架都是这么实现的,就是通过委托或者直接绑定事件,把用户所有可能关注的事件都找出来,然后在这个事件中从DOM上获取数据,并添加回去,唯一的区别在于,没实现双向绑定的框架,只能监控事件,而不能监控属性,所以你通过要这么写:model.price = function () {
if(model.name === '张三') {
return 10;
// 在HTML上写&input on-click="onNameChanged" value="${name}"&
model.onNameChanged = function (e) {
model.setValue('name', e.value);
喜欢用React的朋友是不是经常写这样的代码呢?当然大家都是很懒的,并不想每次都绑定这样的事件,我们喜欢写成这样:// 在HTML中写:&input value="${name}"&
model.price = function () {
if(model.name === '张三') {
return 10;
让框架去自动识别要绑定什么事件,然后获取数值好了,我只管写我的业务逻辑。三、为什么选择表单大家都知道MVVM是通用解决方案,所以我们要考虑的情况非常的多,比如:如果在模板中实现for循环,如果在模板中书写if。focus、submit、change等等事件都怎么绑定。CSS里面的绑定怎么处理。要不要处理单位。NaN !== NaN。因此,我觉得在出题的时候要把题目出的小一点,谁也不希望大家写5000多行 - 30000多行的小练习吧,我自己也没有尝试过这么多。选择表单有以下几个好处:1、我们可以认为表单是不变的,所以for/if啊什么的复杂指令通通可以不要。2、所有有可能出问题的事件比如submit、focus、change等等都有涉及。3、CSS之类的变化不明显,我们可以辅助一些额外的DOM操作来解决样式变化的问题,让MVVM部分只关注表单自身。4、对双向绑定有强需求,大家不会偷懒。5、可以不用自定义模板,用HTML默认的属性就可以了。6、表单操作和表单验证是大家都会遇到的问题,只要把这个弄明白了,就算不用MVVM,你也学到东西了。四、框架可用性和可扩展性以及两者之间的取舍MVVM很好用,但不是万能的,任何一个MVVM框架都是注重数据 & 交互 & 效果的,在很多实际的问题中,我们不可能使用MVVM框架解决所有实际问题,这样要求我们的框架需要和其它框架或者DOM操作有协同能力。所以如何平衡框架的可用性和可扩展性,会成为框架实现到最后一个要纠结的问题,希望大家有自己的想法,我也没有什么标准。但是我一直在尝试,让DOM操作和MVVM结合起来,一个管数据一个管交互和效果,不过这就不是框架该解决的问题了,希望大家可以自行体会。
已有帐号?
无法登录?
社交帐号登录
百度EFE码农建议使用扫描
更多精彩内容请访问&&&
赚礼券,换大礼!
快来登录众测平台,赚礼券兑换丰厚实物大礼!
iPad、小米、百度U盘,海量礼品等您拿!
人人都是产品经理!
报BUG、提优化,请把您天马行空的创意反馈给我们;
如新功能建议被采纳,还有惊喜奉上哦!
&2014 Baidu&&&&百度拇指医生
&&&普通咨询
您的网络环境存在异常,
请输入验证码
验证码输入错误,请重新输入我参加的:
&&&&&&&&&&&&
我们网站有200万的威客为您服务
有才能的在这做威客,赚得真金白银
任务分类威客可以挑选自己感兴趣的任务来参与
本期我们专访的雇主是发布任务的余先生,余先生在公司主要是负责宣传方面……
雇主发布任务心得  
成功案例推荐
任务金额:12000.00元
任务关注:54928
参加:665 提交:368
您没有开启javascript,请开启
本期我们采访的威客是netslave——黄之平,他是一名外贸公司的设计师……
威客可以在任务中国  
威客承接任务经验
威客服务 
■VI标志/包装设计/价格咨
商业logo设计,包出3-5稿,
LOGO/商标/标志设计◆◆字
"狼烟设计& 是一家位
此页面上的内容需要较新版本的 Adobe Flash Player。
活动合作联系(电话:010-0
QQ:)网站威客网精彩专题活动展示
京公网安备号&是的注册商标

我要回帖

更多关于 百度怎么回答问题 的文章

 

随机推荐