迷你MVVM框架 avalonjs1.5 入门教程
avalon经过几年以后,已成为国内一个举足轻重的框架。它提供了多种不同的版本,满足不同人群的需要。比如avalon.js支持IE6等老旧浏览器,让许多靠政府项目或对兼容性要求够高的公司也能享受MVVM的乐趣。avalon.modern.js支持IE10以上版本,优先使用新API,性能更优,体积更少。avalon.mobile.js在avalon.modern的基础提供了触屏事件的支持,满足大家在移动开发的需求。此外,它们分别存在avalon.xxx.shim版本,指无自带加载器版,avalon.xxx.min版本,指上线压缩版本。
avalon早期严重受到angular与knockout的影响,API与它们很相近,经过多年的发展,渐渐摸索出自己一套模式。腾讯百度阿里等大公司都有部门在使用avalonjs,这有力促进avalon的发展。avalon1.5是一个里程碑的版本,它带来许多全新的特性,让我们编写代码更加爽快。
avalon1.5的下载地址: https://github.com/RubyLouvre/avalon/tree/1.5
- 视图模型
- 非监控属性与监控属性
- 视图模型的作用域
- 扫描机制
- 指令(绑定)
- 数据填充(ms-text, ms-html)
- 模板绑定(ms-include)
- 类名切换(ms-class, ms-hover, ms-active)
- 事件绑定(ms-on,……)
- 显示绑定(ms-visible)
- 插入绑定(ms-if)
- 双工绑定(ms-duplex)
- 样式绑定(ms-css)
- 数据绑定(ms-data)
- 属性绑定(ms-attr)
- 循环绑定(ms-repeat,ms-each,ms-with)
- 动画绑定(ms-effect)
- 自定义标签组件
- 模块间通信及属性监控 $watch,$fire
- 过滤器
- 自定义指令(绑定)
- 加载器
- AJAX
- 路由系统
- 在IE6下调试avalon
- avalon1.4.6到1.5的升级指南
- 其他要注意的地方(更新VM等)
视图模型
avalon与jQuery最大的一个区别是,思维的不同。jQuery要操作一个元素,总是设法找到此元素,想象这个元素是否有ID,有某个类名,存在某个特定的标签下,是父节点的第几个孩子,诸如此类,最后拼凑出一个CSS表达式,然后$(expr)找到元素,然后再进行操作,于是JS代码里满屏$。维护代码的人,总是要对着页面来看看,这表达式是对应某某元素,如果只有ID,类名还好,新手很是写出很长的CSS表达式,导致你最后崩溃掉。
avalon要操作某个元素,就直接在HTML为它添加一些指令,这些指令或者以ms-开头的元素属性,或是标签之间的4个花括号。指令里面存在某些变量,这些变量最后在JS聚集成一个对象,这就叫做VM(View Model, 视图模型)。我们只要操作这个VM的数据变动就行了,页面上就会自动变化。有了这一层的分离,我们在代码量就少能许多操作DOM的代码,专致于业务本身。比如说:
<p>{{aaa}}</p>
相当于jQuery的以下代码:
$(function(){$("p").text(aaa)
})
那我们看看怎么定义一个VM吧。avalon在1.5之前存在两种定义方式,现在1.5只支持新风格,即
var vm = avalon.define({$id: "test",a: 1,b: 2,c: {d: 1},onClick: function(e){e.preventDefault()},arr: [1,2,3]
})
avalon.define是一个非常重要的方法,要求传入一个对象,对象里面必须有$id属性,它是用于指定其在页面的作用范围。
avalon.define会返回一个新对象,它除了之前我们定的属性与方法,还添加了$watch, $events, $fire, $model等属性与方法。
当我们以vm.a = 4来重新赋值时,页面上用到a的地方会自然作出反应,这个行为称之为绑定,有的属性会使用ms-duplex指令绑定到表单元素上,这时反应是双向的,input,select, textarea的值被用户改动时,会自然反应到VM上,而我们对VM上的操作也会反应到表单元素上,这叫做双工绑定
有的东西,你压底只有它只作用一次,如大表格的数据展示,以后没有任何互动交互,那我们有几种方式:
- 将该属性的名字以$开头,以$aaa,这样标识它为非监控属性。
- 将该属性的名字放到$skipArray数组,也能标识它非监控属性,因为有的名字需要前后一致,后端不愿意加$,这种方式更灵活。
- 有的属性我想它在这里可以多次改动,有的则显示就不改了,可以使用单向绑定,需要在ms-*属性的值前面加::,或花括号内部的前面加::
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script src="avalon.js"></script><script>var vm = avalon.define({$id: "test",a: 1,$b: 2,$skipArray: ["a"],c: 3})setTimeout(function () {vm.a = 100vm.$b = 100vm.c = 100}, 3000)</script></head><body><div ms-controller="test"><p>{{a}}不会变</p><p>{{$b}}不会变</p><p>{{::c}}不会变</p><p>{{c}}会变</p></div></body>
</html>
非监控属性与监控属性
VM是一个对象,它除了包含一些必须的方法与属性外,其他的东西就分为两大类,非监控属性与监控属性。
非监控属性,就是我们上面指的以$开头,或是名字定义在$skipArray数组的东西,此外,当某属性的值的类型为函数或元素节点,文本节点,注释节点,文档对象,文档碎片与window时,它们也无法监控。
监控属性则分为4类:
- 当其值为字符串,数值,布尔,undefined, null等简单数据类型时,为监控属性
- 当它定义在$computed对象中时,其值为一个对象,拥有get,set方法,为计算属性。计算属性总是有一个或一个以上的监控属性构成。
- 当其值的类型为数组时,称之为监控数组,我们可以改动它的方法,来同步视图。在1.5中,我们不断可以监听其长度变化,还可以监听其元素或元素的属性变化。
- 当其值为一个对象时,它里面的对象也继续转换为计算属性,监控属性,这个对象我们称之为子VM
在1.5之前的版本,还有一个叫监控函数的东西,即里面包含了某些监控方法。但现在我们不建议这样用,因为在未来的版本,我们打算像angular那样通过纯静态词法分析,就能得到此指令所依赖的所有监控属性。而监控方法则需要使用动态的依赖检测实现。动态依赖检测虽然非常强大,但也非常耗性能。在1.5之前,avalon是完全通过动态依赖检测实现绑定的,1.5是结合静态词法分析与动态依赖检测,未来会一点点改为纯静态词法分析。
var vm = avalon.define({$id: "test",a: 1,$b: 2,$skipArray: ["a"],c: 3, //监控属性d: { //这是子VMdd: {ddd: 3},dd2: 4},arr: [1, 2, 3, 4], //监控数组$computed: {c: {//计算属性cget: function () {return this.a + " " + this.c},set: function (val) {var arr = val.split(" ")this.a = arr[0]this.b = arr[1]}},e: {//计算属性eget: function () {return this.a + 100}}}})
视图模型的作用域
为了方便协作开发的需求,我们引入了作用域的概念。因为一个页面可能很大,分为N个模块,每个模块交同不同的人来编写。这个在移动端的SPA应用中尤为明显。 对于JS,我们可以拆分为N个JS文件,每个JS文件都有自己的VM。页面也是拆成一块块,这可以通过PHP或nodejs的模板贴合起来。而在这之前,我们先为它们加上ms-controller!
ms-controller为一个指令,其值为一个VM的$id,如ms-controller="test",它就会在avalon.vmodels中找到该VM,然后这个元素下方用到的所有指令中的变量,都应该位于此VM。
但如果一个功能模块特别复杂,它用到的字段特别多,意味着这个VM也要定义许多许多属性,而这些属性的某一部分也在其他页面或模块用到,这时我们就需要对它进行拆分,方便重用。拆分后的两个对象或N个对象,avalon允许我们以ms-controller套ms-controller的形式,实现作用域间的数据共享。换言之,如果某变量在当前的VM换不到,它就会往上找,在上面的VM中查找此属性,一直找到为止。这有点像JS的对象属性查找,其实,它像CSS的作用域查找,因为我们还引入了ms-important。ms-important的寓意就是CSS中的important!符号,就在此作用域查找,不往外找!
此外,还有些地方,你不想avalon来处理它们,如script标签的内容,style标签的内容,文章的语法高亮部分,引用别人文章的部分,这个可以使用ms-skip指令来绕开这些无用的区域。
至少,我们学习了ms-controller, ms-important, ms-skip, 更详细可以到新官网上学习
扫描机制
avalon能实现VM与视图之间的互动,最关键的东西就是这个。在有的MVVM框架,这也叫做编译(compile),意即,将视图的某一部分的所有指令全部抽取出来,转换为一个个视图刷新函数,然后放到一个个数组中,当VM的属性变动时,就会执行这些数组的函数。当然数组里面的东西不定是函数,也可能是对象,但里面肯定有个视图刷新函数。这是MVVM框架的核心机制,但怎么抽取出来,每个框架的方式都不一样。avalon将这个过程称之为扫描。扫描总是从某个节点开始。在avalon内部,已经默认进行了一次扫描,从body元素开始描。如果我们为页面插入了什么新内容,而这个区域里面又包括了avalon指令,那么我们就需要手动扫描了。
avalon.scan是avalon第二重要的API,它有两个参数,第一个是元素节点,第二个是数组,里面为一个个VM。当然这两个参数是可选的。但当你手动扫描时,最好都会进去,这样会加快扫描速度,并减少意外。因为所有指令,都扫描后就变移除掉,这包括指定VM用的ms-controller,ms-important!
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script src="avalon.js"></script><script>avalon.ready(function () {var div = document.createElement("div")div.innerHTML = "{{aaa}}"div.setAttribute("ms-controller", "eee")document.body.appendChild(div)var vm = avalon.define({$id: "eee",aaa: 111})avalon.scan(div, vm)})</script></head><body></body>
</html>
指令(绑定)
指令是指写在HTML中的特殊符号,包括以下几种,ms-开头的绑定属性,写在innerText里面的{{}}的插值表达式,类似data-duplex-xxx的辅助指令(data-后面跟着的绑定属性的名字,它们必须与绑定元素定义在同一元素),还有新添加的自定义标签(它们必须带有:号)
新手们或从angular过来的人很容易犯一个错误,就是直接在属性值里面加一个{{}},以为就能绑定了,殊不知avalon为了性能优化,会跳过所有非ms-*属性。
这里拥有所有指令的一览图
数据填充
这里提供ms-text, ms-html两种指令,其他ms-text拥有{{expr}}这个变体,ms-html拥有{{expr|html}}这个变体。当你们页面也使用后端模板拼凑而成时,可能 后端会占用了{{}}界定符,我们可以通过以下配置方式重新指定界定符
avalon.config({interpolate:["{%","%}"]
})
并且我们可以通过avalon.config.openTag, avalon.config.closeTag得到“{%”,"%}"。注意,界定符里面千万别出现<, >,因为这存在兼容性问题。这两个界定符也不能一样,最好它们的长度都大于1。
<script>avalon.define({$id: "test",text: "<b> 1111 </b>"})</script><div ms-controller="test"><div><em>用于测试是否被测除</em>xxxx{{text}}yyyy</div><div><em>用于测试是否被测除</em>xxxx{{text|html}}yyyy</div><div ms-text="text"><em>用于测试是否被测除</em>xxxx yyyy</div><div ms-html="text"><em>用于测试是否被测除</em>xxxx yyyy</div></div>
插值表达式{{}}在绑定属性的使用,只限那些能返回字符串的绑定属性,如ms-attr、ms-css、ms-include、ms-class、 ms-href、 ms-title、ms-src等。一旦出现插值表达式,说明这个整个东西分成可变的部分与不可变的部分,{{}}内为可变的,反之亦然。 如果没有{{}}说明整个东西都要求值,又如ms-include="'id'",要用两种引号强制让它的内部不是一个变量。
模板绑定
ms-include指令是ms-html的有效补充。我们知道ms-html是将VM中某个符合HTML结构的字符串,放到某元素底下解析为节点。但如果这个字符串很大,放在VM上就不合算,这时我们就想到将它到页面的某个位置上(如script, noscript, textarea等能放大片内容的特殊标签)或干脆独立成一个HTML文件。于是前者叫做内部模板,因为是放在页面的内部,后者叫做外部模板。对于前者,我们使用ms-include=“expr”来引用,后者,我们是使用ms-include-src="expr"来引用。src表示一个路径,因此其值往往是一个URL地址,为了大家方便拼接URL,我们允许ms-include-src的值可以使用插值表达式。如ms-include-src="aaa/{{bbb}}.html"。由于我们加载外部模板时是用AJAX实现的,因此大家在调试代码时,必须打开WEB服务器。
<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8" /><script src="avalon.js"></script><script>avalon.define({$id: "test",xxx: "引入内部模板"})</script></head><body ><script type="avalon" id="tpl">here, {{ 3 + 6 * 5 }}</script><div ms-controller="test"><p>{{xxx}}</p><div ms-include="'tpl'"></div></div></body>
</html>
注意,ms-include的值要用引号括起,表示这只是一个字符串,这时它就会搜索页面的具有此ID的节点,取其innerHTML,放进ms-include所在的元素内部。否则这个tpl会被当成一个变量, 框架就会在VM中检测有没有此属性,有就取其值,重复上面的步骤。如果成功,页面会出现here, 2的字样。
如果大家想在模板加载后,加工一下模板,可以使用data-include-loaded来指定回调的名字。
如果大家想在模板扫描后,隐藏loading什么的,可以使用data-include-rendered来指定回调的名字。
由于ms-include绑定需要定义在一个元素节点上,它的作用仅仅是一个占位符,提供一个插入位置的容器。 如果用户想在插入内容后,去掉这容器,可以使用data-include-replace="true"。
avalon在使用ms-include-src 加载外部模板时,会将它们存放到avalon.templateCache对象中,因此我们可以搞出一种架构出来,在上线前,将所有要远程加载的模板全部打包到avalon.templateCache对象中,这样它在发出请求前,先查找此对象,发现存在就不会发出请求了。
注意,无论是ms-include还是ms-include-src都会在其值变化时,请空原元素的所有子孙节点,导致原有数据丢失,里面用到的所有组件重新生成,如果保持原来的节点,可以使用data-include-cache="true"辅助指令。
下面是一个经典的后台系统框架!
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script src="avalon.js"></script><script>avalon.templateCache = {aaa: "<div>这里是非常复杂的HTML结构1</div>",bbb: "<div>这里是非常复杂的HTML结构2</div>"ccc: "<div>这里是非常复杂的HTML结构3</div>"ddd: "<div>这里是非常复杂的HTML结构4</div>"}var vm =avalon.define({$id:"root",tabs:["aaa","bbb", "ccc","ddd"],//所有标签页的名字curTab: "aaa",switchTab: function(el){vm.curTab = el},showLoading: function(){},hideLoading:function(){}})</script></head><body ms-controller="root"><table><tr><td><ul><li ms-repeat="tabs" ms-click="switchTab(el)">{{el}}</li></ul></td><td><!--主内容显示区--><div ms-include-src="curTab" data-include-loaded="showLoading"data-include-rendered="hideLoading"></div></td></tr></table></body>
</html>
更详细的内容可见新官网
类名切换(ms-class, ms-hover, ms-active)
avalon1.5现在只支持新风格,即ms-class="aaa: true"这种形式,此绑定属性的值以冒号分为两部分,前面为类名,后面表示添加或移除。 ms-class="aaa bbb ccc: toggle",当toggle在VM中为true时,它会为元素同时添加aaa, bbb, ccc三个类名。冒号及其后面的东西也不是必须的, 如ms-class="aaa1 bbb2",表示总是为元素添加aaa1,bbb2这两个类名。前面的部分也可以使用插值表达式动态生成,如ms-class="{{className}}:true", className在VM是什么,就会为元素添加什么类名。如果你想为元素添加多个类名绑定,可以使用ms-class-1="aaa: true" ms-class-2="bbb:toggle"来添加。
ms-hover, ms-active与ms-class的用法相同,但它们一个只在鼠标掠过元素上方时添加类名,移走时移除;另一个则在元素获得焦点时(比如点击)添加类名,失去焦点时移除。
更详细的内容可见新官网
事件绑定
我们可以通过ms-on-*为元素绑定各种事件,比如ms-on-click=fn,表示为当前元素绑定点击事件,fn为VM的一个函数。默认地,我们会为fn传入一个参数event,我们已经为它做了兼容处理,因此你在IE下也能使用preventDefault, stopPropagation, pageX, pageY, target, timeStamp, which等标准属性与方法。如果你还想传其他参数,还想用事件对象,可以用$event占位。ms-on-click=fn(aaa, bbb, $events)。此外,我们为所有常用事件做了快捷处理,因此你们还可以这样用,ms-click=fn2, ms-mouseover=fn3, ms-mouseleave=fn4。 注意,事件绑定的值的第一个单词必须是VM中的函数名字,你不能在其值里面使用加减乘除,如 ms-click="aaa+bbb",这样是不对的。如果 你想同时绑定多个点击事件,用法与ms-class,ms-hover一样,在后面加数字就行了。ms-click-1=fn1 ms-click-2=fn2 ms-click-3=fn3。
<!DOCTYPE HTML>
<html><head><title>ms-on</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge" /> <script src="../avalon.js" ></script><script>var model = avalon.define({$id: "test",firstName: "司徒",array: ["aaa", "bbb", "ccc"],argsClick: function(e, a, b) {alert([].slice.call(arguments).join(" "))},loopClick: function(a, e) {alert(a + " " + e.type)},status: "",callback: function(e) {model.status = e.type},field: "",check: function(e) {model.field = this.value + " " + e.type},submit: function() {var data = model.$modelif (window.JSON) {setTimeout(function() {alert(JSON.stringify(data))})}}})</script></head><body><h3 style="text-align: center">ms-on-*</h3><fieldset ms-controller="test"><legend>有关事件回调传参</legend><div ms-mouseenter="callback" ms-mouseleave="callback">{{status}}<br/><input ms-on-input="check"/>{{field}}</div><div ms-click="argsClick($event, 100, firstName)">点我</div><div ms-each-el="array" ><p ms-click="loopClick(el, $event)">{{el}}</p></div><button ms-click="submit">点我</button></fieldset></body>
</html>
<!DOCTYPE HTML>
<html><head><title>ms-on</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge" /> <script src="../avalon.js" ></script><script>var count = 0var vm = avalon.define({$id: "multi-click",str1: "1",str2: "2",str3: "3",click0: function () {vm.str1 = "xxxxxxxxx" + (count++)},click1: function () {vm.str2 = "xxxxxxxxx" + (count++)},click2: function () {vm.str3 = "xxxxxxxxx" + (count++)}})</script></head><body><fieldset><legend>一个元素绑定多个同种事件的回调</legend><div ms-controller="multi-click"><div ms-click="click0" ms-click-1="click1" ms-click-2="click2" >请点我</div><div>{{str1}}</div><div>{{str2}}</div><div>{{str3}}</div></div></fieldset></body>
</html>
一个综合了ms-click, ms-class, 监控数组的例子:
<!doctype hmtl>
<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><title>attribute</title><script type="text/javascript" src="avalon.modern.js"></script><script>var vm = avalon.define({$id: "test",selected: [],array: avalon.range(0, 12),onClick: function (i) {if (vm.selected.indexOf(i) === -1) {vm.selected.push(i)} else {avalon.Array.remove(vm.selected, i)}}})</script><style>b{background: gray;-moz-border-radius: 15px; /* Gecko browsers */-webkit-border-radius: 15px; /* Webkit browsers */border-radius:15px; /* W3C syntax */width:30px;height:30px;display: inline-block;line-height: 30px;text-align: center;}b.toggle{background: red;}</style></head><body ms-controller="test"><p ms-each="array"><b ms-click="onClick($index)" ms-class="toggle: selected.indexOf($index)!==-1">{{$index}}</b> </p></body>
</html>
更详细的内容可见新官网
显示绑定(ms-visible)
ms-visible="expr"是通过改变元素的style.display值来控制元素的显示隐藏。
在1.5中结合动画指令还可以使用动画效果。
<!DOCTYPE HTML>
<html><head><title>ms-visible</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge" /> <script src="../avalon.js" ></script><script>avalon.define({$id: "test",a: true})</script><style>.rect{width:100px;height:100px;background: red;display: none;border:1px solid red; text-align: center}</style></head><body><h3>ms-visible</h3><div ms-controller="test"><p>点我隐藏或显示下面的方块<input ms-duplex-checked="a" type="radio"></p><div class="rect" ms-visible="a" >visible</div></div></body>
</html>
更详细的内容可见新官网
插入绑定(ms-if)
ms-if 与 ms-visible的效果很像,都是不显示元素,但ms-if更进一步,将元素移出原来的位置藏到别处。并且它还会延迟其内容元素的扫描与绑定,因此相对于ms-visible性能更好。如果你想ms-if 与ms-repeat用在同一元素,让某个不合格的数组元素代表的那个地方不显示出来,那你请务必使用ms-if-loop!
在1.5中结合动画指令还可以使用动画效果。
<!DOCTYPE HTML>
<html><head><title>ms-if</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge" /> <script src="../avalon.js" ></script><style>.active{background: blueviolet;}</style><script>var vm = avalon.define({$id: "test",data: {toggle: true},toggle: function () {vm.data.toggle = !vm.data.toggle}});</script></head><body><div class="avalonHide">测试avalonHide</div><div ms-controller="test"><div ms-if="data.toggle" class="active">能动态添加移除</div>{{data.toggle}}<p><button type='button' ms-click='toggle'>点我</button></p></div></body>
</html>
更详细的内容可见新官网
双工绑定(ms-duplex)
MVVM框架中最重要的功能之一,唯一一个能让视图同步VM的指令。值得注意的是,它绑定的元素只是 表单元素,input, textarea, select。
在avalon1.5中,ms-duplex只支持duplex2.0。所谓的duplex2.0是指, 我们可以从表单元素的checked属性,value属性抽取数据,转变成所需要的字符串类型,数值类型,布尔类型或数组类型,或添加更多拦截器进行更多操作。
ms-duplex其实是默认使用了string 拦截器,即相当于ms-duplex-string。
其他内置拦截器分别是ms-duplex-number, ms-duplex-boolean, ms-duplex-checked
名字 | 应用元素 | 效果 |
ms-duplex-checked | radio, checkbox | 将其checked值同步到VM |
ms-duplex-string | 所有表单元素 | 将其value值同步到VM, 对于checkbox, select[multiple=true]会进一步转换为数组 |
ms-duplex-number | 所有表单元素 | 将其value值同步到VM, 对于checkbox, select[multiple=true]会进一步转换为数组; 我们还可以通过data-duplex-number='strong|medium|weak'辅助指令来转换非数值 为strong时,不能转的都转换为0; 为medium时,空字符串会忽略转换,否则转换0或其他数字; 为weak时,不是数值形式的值不做转换 |
ms-duplex-boolean | 所有表单元素 | 将其value值同步到VM, 对于checkbox, select[multiple=true]会进一步转换为数组; 转换方式为,当其值为“true”转换为true,其他都转换为false |
默认地,对于文本域,文本区,密码域,框架是使用oninput事件进笨监听,即用户每改动一个字符都会同步到VM。如果想在失去焦点时同步VM,可以使用 data-duplex-event="change"辅助指令来调整。
另,我们还可以为元素添加一个辅助指令, data-duplex-changed="fn", fn为VM中的一个函数。当元素的值 改动时,它会为回调传入当前的值及回调内部的this指向当前表单元素。
我们还可以在avalon.duplexHooks上添加自己的拦截器。
<!DOCTYPE html>
<html><head><title>ms-duplex</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge" /> <script src="../avalon.js" ></script><script>var model = avalon.define({$id: "test",text: "xxx",textcb: "",textchange: function(a) {model.textcb = a},radio: "radio",radiocb: "",radiochange: function(a) {model.radiocb = a},select: "2222",selectcb: "",selectchange: function(a) {model.selectcb = a}})</script></head><body ms-controller="test"><h3>data-duplex-changed回调</h3><div><input ms-duplex="text" data-duplex-changed="textchange">{{textcb}}</div><div><input ms-duplex-checked="radio" type="radio" data-duplex-changed="radiochange">{{radiocb}}</div><div><select ms-duplex="select" data-duplex-changed="selectchange"><option>1111</option><option>2222</option><option>3333</option><option>4444</option></select>{{selectcb}}</div></body>
</html>
我们可以通过以下方式定义一个拦截器,在avalon.duplexHooks上添加一个对象,此对象拥有init, get, set这三个方法,此三个方法不一定要写全,只要某一个就行了。init在初始化时调用,get方法是同步到VM时调用,set方法是同步视图时调用,这些方法都有两个参数,第一个参数是当前值,第二个参数是绑定对象。
有了拦截器,我们就可以实现各种表单验证,并且一个ms-duplex是可以带N多拦截器的,如ms-duplex-number-notempty-gt10
<!DOCTYPE html>
<html>>head><title>TODO supply a title</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width"><script src="../avalon.js" ></script><script>var model = avalon.define({$id: "test",a: 111});avalon.duplexHooks.add100 = {get: function (val) {return val},set: function (val) {return val + 100}}</script></head><body><div ms-controller="test"><input ms-duplex-number-add100="a" >{{a}}</div></body>
</html>
avalon的oniui的验证组件也是基于拦截器机制构建的,大家可以参考一下,方便自己设计自己的表单验证。
更详细的内容可见新官网
样式绑定(ms-css)
用法为ms-css-name="value"。其值可以使用插值表达式, 如ms-css-width=”prop”(会自动补px),ms-css-height=”{{prop}}%”, ms-css-color=”prop”, ms-css-background-color=”prop”, ms-css-background-image=”url({{imageUrl}})”, ms-css-font-size=”{{prop}}px”
注意:属性值不能加入CSS hack与important!
<!DOCTYPE html>
<html><head><title>by 司徒正美</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><script src="../avalon.js"></script><script>avalon.define({$id: "test", o: 0.5, bg: "#F3F"// 不能使用CSS hack,如 bg : "#F3F\9\0"})</script><style>.outer{width:200px;height: 200px;position: absolute;top:1px;left:1px;background: red;z-index:1;}.inner{width:100px;height: 100px;position: relative;top:20px;left:20px;background: green;}</style></head><body ms-controller="test" ><h3>在旧式IE下,如果父元素是定位元素,但没有设置它的top, left, z-index,那么为它设置透明时,它的所有被定位的后代都没有透明</h3><div class="outer" ms-css-opacity="o" ms-css-background-color="bg" ><div class="inner"></div></div></body>
</html>
更详细的内容可见新官网
数据绑定(ms-data)
为当前元素添加data-*属性。可以参见ms-attr的用法。
更详细的内容可见新官网
属性绑定(ms-attr)
其用法为ms-attr-name="value", value可以使用插值表达式。当value为undefined, null, false,会移除此属性,否则会添加此属性。
<!DOCTYPE html>
<html><head><title>ms-attr-*</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width"><script src="../avalon.js"></script><script>var vm = avalon.define({$id: "test",aaa: true,bbb: "@@@",ccc: "&&&",active: "active",click: function(){vm.aaa = !vm.aaa}})</script><style>.active {background: goldenrod;}.readonly{border:1px solid blueviolet;}</style></head><body><form method="get" action="aaa.html" ms-controller="test"><input ms-enabled="aaa" name="a1" value="12345"/><input ms-disabled="aaa" name="a2" value="67890"/><input ms-readonly="aaa" name="a3" ms-class="readonly: aaa" value="readonly" /><input ms-duplex-radio="aaa" type="checkbox" value="checkbox" name="a4"/><select name="a5"><option>222</option><option ms-selected="aaa">555</option></select><p><input ms-attr-value="其他内容 {{ccc}}" name="a6" value="改"/><input ms-attr-value="'其他内容 '+ccc" name="a7" value="改" /><input ms-value="其他内容 {{ccc}}" name="a8" value="改"/></p><button type="button" ms-click="click" ms-attr-class="active">点我</button><input type="submit" value="提交" /><svg width="100" height="100"><circle ms-attr-cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" /></svg></form></body>
</html>
更详细的内容可见新官网
循环绑定(ms-repeat, ms-each, ms-with)
这三个东西都很相像,见下表
名字 | 循环的类型 | 循环的范围 |
ms-repeat | 用于循环数组与对象 | 循环当前元素 |
ms-each | 用于循环数组 | 循环当前元素的内部 |
ms-with | 用于循环对象 | 循环当前元素的内部 |
当我们用ms-each, ms-repeat循环数组时,可以为元素指定其别名,如ms-each-item="array1", ms-repeat-elem="array2", 如果你不指定别名,则默认为el。(注意,别名不能出现大写,因为属性名在HTML规范中,会全部转换为小写,详见这里)。监控数组拥有原生数组的所有方法,并且比它还多了set, remove, removeAt, removeAll, ensure, pushArray与 clear方法 。详见这里。
注意,ms-each, ms-repeat会生成一个新的代理VM对象放进当前的vmodels的前面,这个代理对象拥有el, $index, $first, $last, $remove, $outer等属性。另一个会产生VM对象的绑定是ms-widget。
- el: 不一定叫这个名字,比如说ms-each-item,它就变成item了。默认为el。指向当前元素。
- $first: 判定是否为监控数组的第一个元素
- $last: 判定是否为监控数组的最后一个元素
- $index: 得到当前元素的索引值
- $outer: 得到外围循环的那个元素。
- $remove:这是一个方法,用于移除此元素
我们还可以通过data-repeat-rendered, data-each-rendered来指定这些元素都插入DOM被渲染了后执行的回调,this指向元素节点, 有一个参数表示为当前的操作,是add, del, move, index还是clear
如果循环的是对象,那么代理VM就有$val, $key, $index, $outer等属性。$key, $val分别引用键名,键值。另我们可以通过指定data-with-sorted回调,规定只输出某一部分建值及它们的顺序。 注意,此绑定已经不建议使用,它将被ms-repeat代替,ms-repeat里面也可以使用data-with-sorted回调。
<!DOCTYPE html>
<html><head><title></title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><script src="avalon.js"></script><style>.id2013716 {width: 200px;float:left;}</style><script>var a = avalon.define({$id: "array",array: ["1", "2", "3", "4"]})setTimeout(function() {a.array.set(0, 7)}, 1000);var b = avalon.define({$id: "complex",array: [{name: "xxx", sex: "aaa", c: {number: 2}}, {name: "yyy", sex: "bbb", c: {number: 4}}]//});setTimeout(function() {b.array[0].c.number = 9b.array[0].name = "1000"}, 1000)setTimeout(function() {a.array.push(5, 6, 7, 8, 9)}, 1000)setTimeout(function() {a.array.unshift("a", "b", "c", "d")}, 2000)setTimeout(function() {a.array.shift()b.array[1].name = 7}, 3000)setTimeout(function() {a.array.pop()}, 4000)setTimeout(function() {a.array.splice(1, 3, "x", "y", "z")b.array[1].name = "5000"}, 5000)</script></head><body><fieldset class="id2013716" ms-controller="array"><legend>例子</legend><ul ms-each="array"><li >数组的第{{$index+1}}个元素为{{el}}</li></ul><p>size: <b style="color:red">{{array.size()}}</b></p></fieldset><fieldset class="id2013716" ms-controller="complex"><legend>例子</legend><ul ><li ms-repeat-el="array">{{el.name+" "+el.sex}}它的内容为 number:{{el.c.number}}</li></ul></fieldset></body>
</html>
更详细的内容可见新官网
动画绑定(ms-effect)
avalon1.5新增的功能,允许我们用avalon.effect方法定义一个动画,然后在页面上存在ms-if,ms-repeat,ms-include,ms-visible的元素添加ms-effect="effectName"实现动画效果。此动画可以使用CSS3与JS实现。
更详细的内容可见新官网
自定义标签组件
通过自定义标签声明使用某个组件,这是avalon1.5引入的最重要特性。
早在20年前,JAVA也想通过标签库实现堆积木般的开发。但鉴于当时JAVAer的技术力量,这东西没有做成;现在谷歌有了自己的浏览器,实现了一套WEB Components规范,开源polymer,也是往这条路子走下去。因为以标签的形式声明组件比起在JS里以类的形式创建组件,来得更简单明了。
<oni:buttonset><oni:button color="danger" type="icon" icon-position="left" icon="\&\#xf04c;"></oni:button><oni:button color="danger" type="icon" icon-position="left" icon="\&\#xf04b;"></oni:button><oni:button color="danger" type="icon" icon-position="left" icon="\&\#xf074;"></oni:button>
</oni:buttonset>
做这套东西有几个难点:
- 生命周期管理,从构建配置对象,到模板微调,到初始化,到子组件就绪,到自身组件就绪,到组件销微,都有自己相应的回调。
- 继承机制
- 当前组件必须等到子组件就绪才闭合自身,比如父组件的高度是由子组件决定
- 组件的某些很大块的区块如何定义(这个引入插入点的概念处理),如弹出层有title, content, footer
为了让一个页面使用多个UI库,avalon引入了命名空间的概念,这是来自早期XML的设计。一个标签名由冒号隔开,前面是命名空间,后面是标签名。
avalon.library("oni", {})//这是声明一个命名空间,也是算声明一个UI库
在定义一个UI组件,最少有3个文件,JS文件(引用其他两个文件或更多子组件的JS),HTML文件(组件的模块),CSS文件(它可以由SASS更高级的语言生成)。
define(["avalon","text!./avalon.pager.html","css!../chameleon/oniui-common.css","css!./avalon.pager.css"
], function (avalon, template) {var _interface = function () {}avalon.component("oni:pager", {regional: {}, //@config {Object} 默认语言包perPages: 10, //@config {Number} 每页包含多少条目showPages: 10, //@config {Number} 中间部分一共要显示多少页(如果两边出现省略号,即它们之间的页数) currentPage: 1, //@config {Number} 当前选中的页面 (按照人们日常习惯,是从1开始),它会被高亮 _currentPage: 1, //@config {Number} 跳转台中的输入框显示的数字,它默认与currentPage一致totalItems: 200, //@config {Number} 总条目数totalPages: 0, //@config {Number} 总页数,通过Math.ceil(vm.totalItems / vm.perPages)求得pages: [], //@config {Array} 要显示的页面组成的数字数组,如[1,2,3,4,5,6,7]ellipseText: "…", //@config {String} 省略的页数用什么文字表示 prevText: "", //@config {String} “上一页”分页按钮上显示的文字 firstPage: 0, //@config {Number} 当前可显示的最小页码,不能小于1$ready: function(){//....}//....})
})
avalon.component是用来定义一个组件,第一个参数为自定义标签的名字(包括命名空间),第二个是配置对象,里面定义这个组件用到的属性,状态与方法。
如何做一个avalon组件
更详细的内容可见新官网
我们也可以到这里直接看pager, button, checkboxlist是怎么定义。
未来与avalon配套使用的OniUI一点点全部改成自定义标签的形式,更希望大家一起为avalon设计更多的UI组件。
模块间通信及属性监控 $watch,$fire
avalon1.5是无比强大,并现在只有VM第一层有$watch, $fire方法,并去掉$unwatch方法。$watch方法会返回一个方法,调用它就会去掉此回调。
早期$watch只能监听当前层的属性,不能监听其子对象的属性,尤其在数组中,无法监听元素的属性变动。因此在avalon1.5中,引入通配符及多级监听功能。
var vm = avalon.define({$id: "test",array: [1, 2, 3],arr: [{a: 1}, {a: 2}, {a: 3}],obj: {a: 1,b: 2},a: {b: {c: {d: 33}}}})vm.$watch("array.*", function (a, b) {expect(a).to.be(6)expect(b).to.be(2)})vm.$watch("arr.*.a", function (a, b) {expect(a).to.be(99)expect(b).to.be(1)})vm.$watch("obj.*", function (a, b, c) {expect(a).to.be(111)expect(b).to.be(1)})vm.$watch("a.*.c.d", function (a, b, c) {expect(a).to.be(88)expect(b).to.be(33)})setTimeout(function () {vm.array.set(1, 6)vm.arr[0].a = 99vm.obj.a = 111vm.a.b.c.d = 88}, 100)
注意,*通配任只能出现一次
var unwatch = vm.$watch("array.*", function (a, b) {expect(a).to.be(6)expect(b).to.be(2)})
unwatch() //移除当前$watch回调
如果在跨模块通信,由于所有VM都储存在avalon.vmodels中,我们可以遍历它们,找到目标VM,然后$fire。
avalon多级联动例子:
<!DOCTYPE html>
<html><head><title>三级联动</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script src="avalon.js"></script><script>var map = {"中国": ["江南四大才子", "初唐四杰", "战国四君子"],"日本": ["日本武将", "日本城堡", "幕府时代"],"欧美": ["三大骑士团", "三大魔幻小说", "七大奇迹"],"江南四大才子": ["祝枝山", "文征明", "唐伯虎", "周文宾"],"初唐四杰": ["王勃", "杨炯", "卢照邻", "骆宾王"],"战国四君子": ["楚国春申君黄歇", "齐国孟尝君田文", "赵国平原君赵胜", "魏国信陵君魏无忌"],"日本武将": ["织田信长", "德川家康", "丰臣秀吉"],"日本城堡": ["安土城", "熊本城", "大坂城", "姬路城"],"幕府时代": ["镰仓", "室町", "丰臣", "江户"],"三大骑士团": ["圣殿骑士团", "医院骑士团", "条顿骑士团"],"三大魔幻小说": ["冰与火之歌", "时光之轮", "荆刺与白骨之王国"],"七大奇迹": ["埃及胡夫金字塔", "奥林匹亚宙斯巨像", "阿尔忒弥斯月神殿", "摩索拉斯陵墓", "亚历山大港灯塔", "巴比伦空中花园", "罗德岛太阳神巨像"]}var vm = avalon.define({$id: "test",first: ["中国", "日本", "欧美"],second: [],third: [],firstSelected: "日本",secondSelected: "日本武将",thirdSelected: "织田信长"})vm.second = map[vm.first[1]].concat()vm.third = map[vm.second[0]].concat()vm.$watch("firstSelected", function (a) {vm.second = map[a].concat()vm.secondSelected = vm.second[0]})vm.$watch("secondSelected", function (a) {vm.third = map[a].concat()vm.thirdSelected = vm.third[0]})</script></head><body><div ms-controller="test"><h3>下拉框三级联动</h3><select ms-duplex="firstSelected" ><option ms-repeat="first" ms-attr-value="el" >{{el}}</option></select><select ms-duplex="secondSelected" ><option ms-repeat="second" ms-attr-value="el" >{{el}}</option></select><select ms-duplex="thirdSelected" ><option ms-repeat="third" ms-attr-value="el" >{{el}}</option></select></div></body>
</html>
过滤器
avalon从angular中抄来管道符风格的过滤器,但有点不一样。 它只能用于{{}}插值表达式。如果不存在参数,要求直接跟|filter,如果存在参传,则要用小括号括起,参数要有逗号,这与一般的函数调用差不多,如|truncate(20,"……")
avalon自带以下几个过滤器
- html
- 没有传参,用于将文本绑定转换为HTML绑定 sanitize
- 去掉onclick, javascript:alert等可能引起注入攻击的代码。 uppercase
- 大写化 lowercase
- 小写化 truncate
- 对长字符串进行截短,truncate(number, truncation), number默认为30,truncation为“...” camelize
- 驼峰化处理 escape
- 对类似于HTML格式的字符串进行转义,把尖括号转换为> < currency
- 对数字添加货币符号,以及千位符, currency(symbol) number
- 对数字进行各种格式化,这与与PHP的number_format完全兼容, number(decimals, dec_point, thousands_sep),
decimals 可选,规定多少个小数位。dec_point 可选,规定用作小数点的字符串(默认为 . )。thousands_sep 可选,规定用作千位分隔符的字符串(默认为 , ),如果设置了该参数,那么所有其他参数都是必需的。
date - 对日期进行格式化,date(formats)
'yyyy': 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)'yy': 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)'y': 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)'MMMM': Month in year (January-December)'MMM': Month in year (Jan-Dec)'MM': Month in year, padded (01-12)'M': Month in year (1-12)'dd': Day in month, padded (01-31)'d': Day in month (1-31)'EEEE': Day in Week,(Sunday-Saturday)'EEE': Day in Week, (Sun-Sat)'HH': Hour in day, padded (00-23)'H': Hour in day (0-23)'hh': Hour in am/pm, padded (01-12)'h': Hour in am/pm, (1-12)'mm': Minute in hour, padded (00-59)'m': Minute in hour (0-59)'ss': Second in minute, padded (00-59)'s': Second in minute (0-59)'a': am/pm marker'Z': 4 digit (+sign) representation of the timezone offset (-1200-+1200)format string can also be one of the following predefined localizable formats:'medium': equivalent to 'MMM d, y h:mm:ss a' for en_US locale (e.g. Sep 3, 2010 12:05:08 pm)'short': equivalent to 'M/d/yy h:mm a' for en_US locale (e.g. 9/3/10 12:05 pm)'fullDate': equivalent to 'EEEE, MMMM d,y' for en_US locale (e.g. Friday, September 3, 2010)'longDate': equivalent to 'MMMM d, y' for en_US locale (e.g. September 3, 2010'mediumDate': equivalent to 'MMM d, y' for en_US locale (e.g. Sep 3, 2010)'shortDate': equivalent to 'M/d/yy' for en_US locale (e.g. 9/3/10)'mediumTime': equivalent to 'h:mm:ss a' for en_US locale (e.g. 12:05:08 pm)'shortTime': equivalent to 'h:mm a' for en_US locale (e.g. 12:05 pm)
例子:
生成于{{ new Date | date("yyyy MM dd:HH:mm:ss")}}
生成于{{ "2011/07/08" | date("yyyy MM dd:HH:mm:ss")}}
生成于{{ "2011-07-08" | date("yyyy MM dd:HH:mm:ss")}}
生成于{{ "01-01-2000" | date("yyyy MM dd:HH:mm:ss")}}
生成于{{ "03 04,2000" | date("yyyy MM dd:HH:mm:ss")}}
生成于{{ "3 4,2000" | date("yyyy MM dd:HH:mm:ss")}}
生成于{{ 1373021259229 | date("yyyy MM dd:HH:mm:ss")}}
生成于{{ "1373021259229" | date("yyyy MM dd:HH:mm:ss")}}
值得注意的是,new Date可传的格式类型非常多,但不是所有浏览器都支持这么多,详看这里
多个过滤器一起工作
<div>{{ prop | filter1 | filter2 | filter3(args, args2) | filter4(args)}}</div>
如果想自定义过滤器,可以这样做
avalon.filters.myfilter = function(str, args, args2){//str为管道符之前计算得到的结果,默认框架会帮你传入,此方法必须返回一个值/* 具体逻辑 */return ret;}//默认过滤器avalon.filters.default = function(str, defaultStr){return str || defaultStr}//性别过滤器avalon.filters.sex = function(str){return str == '0' ? '男': '女'}
自定义指令(绑定)
avalon1.5新添加的API,avalon.directive, 用于快速创建一种全新的指令!
过去avalon自定义绑定比较麻烦,非常影响avalon推广,也不利于业务上各种功能的开发,新的定义方式将变得非常简单
avalon.directive(name, {init: function(binding){//在这里处理binding.expr属性},update: function(value, oldValue){//value是binding.expr经过解析得到的当前VM属性的值//oldValue是它之前的值},
})
拿最简单的data绑定来说吧:
avalon.directive("data", {priority: 100,update: function (val) {var elem = this.elementvar key = "data-" + this.paramif (val && typeof val === "object") {elem[key] = val} else {elem.setAttribute(key, String(val))}}
})
我们发现它没有init回调,init主要是对binding.expr进行加工,或绑定事件的,它这些都不需要, 就会直接返回原始值.比如说,<div ms-data-xxx="yyy"< 这里的属性会抽取成下面一个对象:
var binding = {name: "ms-data-xxx",expr: "yyy",type: name,element: DIVElement,param: "xxx",oneTime: false,uuid: //框架会在这里生成一个UUID给它priority://框架会根据上面的定义,计算出来,大概是1000+ ;
}
假如此时vm.yyy = 999; 那么第一次update时,value与oldValue分别为 999, undefined
对于用户来说,priority一般不需要设置, 其计算公式为
//详见 scanAttr
priority: (directives[type].priority || type.charCodeAt(0) * 10) + (Number(param.replace(/\D/g, "")) || 0)
此外,如果你的绑定需要绑定一些事件来监听用户行为,那么你得在init或update添加一个roolback回调,在里面解绑定事件.
update方法中的this就是init的传参binding
那么我们做一下简单的例子吧:
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script src="avalon.js"></script><script>avalon.directive("foo", {init: function (binding) {var elem = binding.elementvar vmodels = binding.vmodelsvar remove = avalon(elem).bind("click", function () {elem.innerHTML = new Date - 0for (var i = 0, v; v = vmodels[i++]; ) {if (v.hasOwnProperty(binding.expr)) {v[binding.expr] = elem.innerHTMLbreak}}})binding.roolback = function () {avalon(elem).unbind("click", remove)}},update: function (value, oldValue) {this.element.innerHTML = value}})var vm = avalon.define({$id: "test",aaa: 111})vm.$watch("aaa", function (a, b) {console.log(a, b)})</script></head><body><div ms-controller="test"><div ms-foo="aaa">点我</div></div></body>
</html>
别看例子简单,其实它是除duplex外又一个新的双工绑定!
加载器
avalon自带加载器,它是使用业界最通用的AMD规范。
如果你想禁用自带加载器,有两种办法:
- 先入avalon再引入其他加载器,然后立即禁用avalon自带加载器
avalon.config({loader:false })
- 到这里下载没有加载器的版本(以shim结尾)
至于avalon是怎么与jQuery, requirejs怎么搭配,怎么打包,可以详看这里。
AJAX
avalon本身没提供AJAX模块,大家可以使用jQuery或 mmRequest
require(["mmRequest/mmRequest"], function() {var vm = avalon.define("test", function(vm) {vm.loadScript = function() {avalon.getScript("test.js", function() {console.log("success")vm.time = + new Date()})}vm.loadAJAX = function() {avalon.ajax({url: "test.js",dataType: "script",data: {page: 1,name: 1},success: function() {console.log("success")vm.time = + new Date()}})}vm.jsonData = []vm.time = ""})avalon.scan()})
mmRequest覆盖原jQuery所有的功能,其文档地址在这里。
如果我们想将VM提交到后台,由于VM存在许多方法与其他东西,直接提交数据量很大,因此我们可以通过下面方法提交纯数据
$("button").keyup(function(){$.post("demo_ajax_gethint.asp", JSON.parse(JSON.stringify(vm.$model)),function(result){alert("提交成功")});
});
路由系统
avalon提供了mmRouer与mmState两个路由器,但mmState也是基于mmRouter开发的,引入mmState就会自动引入mmRouter。
这里两个加载器都可以在这里下载到,包括(mmPromise, mmHIstory, mmRouter, mmState)
其文档放在这里,有不懂的地方直接在此仓库提ISSUE
在IE6下调试avalon
由于IE6下没有console.log,如果又不想用VS等巨无霸IDE,可以自己定义以下方法
if(!window.console){window.console = {}console.log = function(str){avalon.ready(function() {var div = document.createElement("pre");div.className = "mass_sys_log";div.innerHTML = str + ""; //确保为字符串document.body.appendChild(div);});}}
上线后,将.mass_sys_log{ display: none; }
如果是高级浏览器,avalon会在控制台上打印许多调试消息,如果不想看到它们,可以这样屏蔽它们:avalon.config({debug: false})
avalon1.4.6到1.5的升级指南
- avalon1.5不再支持旧风格,avalon.define(id, callback)全部改成avalon.define(object)这种形式
- avalon1.5定义计算属性时,需要在$computed对象上统一定义
- avalon1.5生成的VM 只有第一层对象上拥有 $fire, $watch方法,子对象没有$fire, $watch方法。之前监听数组长度变化时,是用vm.array.$watch("length",callback),现在改成vm.$watch("array.length",callback),之前监听子对象某个属性的变化,是使用vm.aaa.$watch("bbb",callback),现在改成vm.$watch("aaa.bbb",callback),之前监听某一层的所有属性变化是vm.$watch("all!", callback),现在改成vm.$watch("*",callback);之前不能监听数组元素变化,现在可以vm.$watch("array2.*", callback)
- avalon1.5不再支持$unwatch,详见上方。
- avalon1.5不再支持data-duplex-focus, data-duplex-observe辅助指令
- avalon1.5不再支持ms-widget,请使用avalon.component创建组件,然后以自定义标签的形式声明使用。
- avalon1.5不再使用avalon.bindingHandlers,avalon.bindingExecutors来创建新指令,再改用更方便的avalon.directive方法
- avalon在循环对象时,以前需要自己计算索引值,现在它与循环数组一样,存在$index变量了!
其他要注意的地方(更新VM等)
avalon是通过Object.defineProperty来实现属性监听,因此不像angular,每次都VM的所有属性都比较一遍,而是用户一改动属性就立即触发视图变动。
这是avalon的优势,但隐藏一个不好的地方。用户必须在avalon.define的配置对象将所有监听的对象预先写好,否则无法监听到。
var vm = avalon.define({$id: "test",a: "aaa", //这个可以监听,改变它会同步视图$b:"ccc" //这个是非监控属性,改变它不会同步视图})vm.c = '111' //这是avalon.define后才添加的,改变它不会同步视图//在IE6-8还会抛错
avalon在IE6-8是使用VBScript实现,不支持随便添加新属性,比如上例就会抛错
VBScript还带一个问题,它是不区分大小写,aaa与AAA是认为一样的,这时它会报重复定义的问题。
某些属性由于是VBscript的关键字,也不能作为属性或方法,否则在IE6-8也抛错,如type, err, erm, me
由于avalon是通过Object.defineProperty来实现属性监听,它会转换其底下的每一个属性,每一个数组,每一个子对象,因此对象的层次不太深,否则会带来性能问题。最好不超过3层,数组的层次也宜过长。并且尽量使用$开头或放在$skipArray减少无谓的属性监听。
avalon可以通过以下手段撕开不能监听新属性的限制,就是重写子对象!
var vm = avalon.define({$id: "test",a: {}})vm.a = {b: 2,//现在a.b, a.c, a.d可以与视图互相同步了c: 3d: 4}
如果你想重写数组的某一个元素,可以其set方法,如果交互两个数组元素,请使用splice方法或深拷贝原数组再赋值。
<!DOCTYPE html>
<html lang="zh-cn"><head><meta charset="utf-8"><script src="avalon.js"></script><script>var vm = avalon.define({$id: "test",items: [{name: 'First lady'},{name: 'Second boy'},{name: 'Third guy'}];});var temp = vm.items.splice(2, 1);vm.items.splice(1, 0, vm[0].$model);//如果是简单数据类型,就不需要.$model</script></head><body><ul ms-controller="test"><li ms-repeat="items">{{ el.name }}</li></ul></body>
</html>
<!DOCTYPE html>
<html><head><title>avalon入门</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><script src="avalon.js" type="text/javascript"></script><script>var model = avalon.define({$id: 'test',arr: [{'value': '0','text': 'zero'}, {'value': '1','text': 'one'}, {'value': '2','text': 'two'}, {'value': '3','text': 'three'}],click: function () {var aa = avalon.mix(true, [], model.$model.arr)//交换one和threeaa[1] = aa[3]aa[3] = aa[1]//控制台显示交换成功console.log(aa[1])console.log(aa[3])model.arr = aa}})</script></head><body><div ms-controller="test"><button type="button" ms-click="click">xxx</button><ul><li ms-repeat="arr" >{{el.text}}</li></ul></div></body></html>
与mmState搭配使用时,页面上的组件重复生成的解决方法:在ms-view所在元素上添加一属性data-view-cache="true", 。但如果两个视图有相同的dialog(就是ms-include-src='路径.html')相互之前切换的话dialog vmodels会被删除。就把调用公用dialog的html移除到ms-view之外解决了。
我们可以在官网或这里看到更多有用的信息
有问题请到GITHUB提ISUUE,或到avalon专门论坛提问。
avalon在慕课网也有相关视频教程, 前端乱炖上有系列长文剖析avalon的原理
本人也承受北京地区的avalon上门培训!!!
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 前言——前端转型之殇
前言——前端转型之殇 比人本是一名Android开发人员,奈何受到创业大潮之洗脑,义无反顾加入了创业大军。辗转反侧,摸爬滚动,偶然机会需要进行前端整站架构开发。浏览器兼容、PC\APP\微信三端兼容、SEO、服务端渲染加速等࿰…...
2024/5/8 14:41:30 - javascript实现数据双向绑定的三种方式
前端数据的双向绑定方法前端的视图层和数据层有时需要实现双向绑定(two-way-binding),例如mvvm框架,数据驱动视图,视图状态机等,研究了几个目前主流的数据双向绑定框架,总结了下。目前实现数据双向绑定主要有以下三种。…...
2024/5/8 14:11:36 - Web应用的组件化(一)——基本思路
原文链接:https://github.com/xufei/blog/issues/6 1. 为什么要做组件化? 无论前端也好,后端也好,都是整个软件体系的一部分。软件产品也是产品,它的研发过程也必然是有其目的。绝大多数软件产品是追逐利润的…...
2024/4/26 6:54:41 - 前端入门参考:写给前端入门者的chat
前端是什么 众多IT岗位中的一员,以HTMLCSSJS开发网站、微信公众号、小程序、WEBAPP的岗位,一个夹杂与UI与后台间的岗位。工作流程为从UI处得到原型图或者效果图,在项目(网站、微信公众号、小程序、WEBAPP)中还原图片效…...
2024/4/21 4:25:38 - Hybrid移动应用在多页面大数据复杂业务背景下的优化实践方案
前言 对于混合应用而言,性能问题一直被吐槽,虽然设备的内存的不断增大,很大程度上缓解了这个一问题,但是和原生应用来讲还是有很大区别,本人从Phonegap2.x开始,一直的探索和使用混合应用技术。 当时的2.x…...
2024/4/21 4:25:37 - 前端开发 20 年变迁史
【CSDN 编者按】1990年,第一个Web浏览器诞生,而WWW的诞生直接拉开前端史的序幕。 从静态页面到JavaScript,从依赖后端到自主开发,前端开发者从不被重视的“页面仔”逆袭为如今很多前端工程师的薪资比后端还高,从前端技…...
2024/5/8 19:46:44 - 2015前端框架何去何从
这篇文章将从 AngularJS ReactJS Polymer 这几个流行的框架入手,分析前端框架在这几年发展中的关键技术点,作为2015前端技术选型的参考。摘要: 初体验技术特点组件化应用架构总结 1. 初体验 拿TODO来作为引子好了. Angular 的实现 React的实现(非flux架构…...
2024/4/20 4:03:42 - avalon v0.4发布,迷你简单易用的MVVM框架
avalon已经从mass Framework抽取出来,没有任何依赖。 主要优点如下 使用简单,在HTML中添加绑定,在JS中用avalon.define定义ViewModel,再调用avalon.scan方法,它就能动了!兼容到IE6没有任何依赖,…...
2024/5/9 3:36:47 - 轻量级前端MVVM框架avalon - 执行流程2
接上一章 执行流程1 在这一大堆扫描绑定方法中应该会哪些实现? 首先我们看avalon能帮你做什么? 数据填充,比如表单的一些初始值,切换卡的各个面板的内容({{xxx}},{{xxx|html}}, ms-html)类名处理,如隔行变色࿰…...
2024/4/20 19:49:33 - 迷你MVVM框架 avalon的魔术
本文将深入介绍一下avalon的运作机理及与jQuery的区别。 许多人都知道MVVM是MVC的一个变体,但那些MVC是在后端的,包括微软的WPF,这意味着这个V与我们前端接触到的V差别很大。后端的V就是使用各种模板拼凑成一个静态页面给前端。而前端的V在JS…...
2024/4/21 4:25:35 - avalon.js的循环操作在表格中的应用
avalon.js的循环操作在表格中的应用一个JAVA开发,因为做的门户系统中,数据的展示加载的速度很影响使用效果,想到的是尽量少的请求后台,然后接触到了avalon,看介绍这是一个很轻很轻的MVVM架构的前端框架。我用的是avalo…...
2024/4/24 19:06:31 - angular4之时间戳转日期格式
前言: 最近在做前端的项目,刚开始做还是很羞涩的样子,不过好在有百度下大神的无私奉献还有我们家欢哥的热情帮助,这个问题解决了,宝宝只负责记录一下(虽然是我的任务)下面进入主题:之前: 之后:之前我是在html中试着调ts中的方法,保存之前整个界面都没了,虽然你挺难…...
2024/4/21 4:25:33 - 用Angular制作单页应用视图切换动画
视图,动画 单页应用(Single Page Web Application)往往有一个基本的要点,那就是把多个视图集成到一个网页内,然后去控制这些视图的显示和隐藏。此外,视图的切换动作几乎都会引入动画效果,以获得…...
2024/4/21 4:25:33 - Ionic4+Angular8实现App主题样式切换
Ionic4Angular8实现App主题样式切换背景前置条件正文部分实现效果实现过程1、创建主题样式文件2、修改src/theme/variables.scss,导入刚刚创建的3个样式文件3、通过ionic g脚手架命令创建一个service4、通过观察者模式完善SettingsService5、修改src/app/app.compon…...
2024/5/6 12:52:29 - angular 变更检测机制,视图中点击按钮后不能切换数据,再次点击按钮后才显示正确的列表内容
要实现的效果 出现的问题 本地上测试一切正常,打包后上传成元部件,发不成部件以后出现以下问题 1、页面初次加载列表内容显示正常、数量也显示正常 2、点击预警按钮不显示预警列表,点击报警按钮后显示预警的列表,再次点击报警按钮…...
2024/4/21 4:25:30 - AngularDart Material Design 切换
2019独角兽企业重金招聘Python工程师标准>>> MaterialToggleComponent Selector: <material-toggle> material-toggle是一个可以是ON或OFF的按钮。 用户可以点击切换按钮来更改状态。 通常,当您有一个ON / OFF选项时,您可以使用切换按钮…...
2024/4/21 4:25:30 - angular4中组件之间页面切换的数据传递,通过路由传递数据
例如在表格中有一个详情按钮,跳转到另外一个页面, 首先需要在所在页面和跳转页面引入路由组件和跳转界面路由组件 selectMsg(productID:number,productName:any,productCome:any){ // 跳转页面 return this.router.navigate([product-element,{"p…...
2024/4/26 13:17:38 - 用JQuery和angularjs分别实现两个盒子间按钮的跳转(第二版)
精简了jQuery代码 不足之处做了改进; html: <!DOCTYPE html> <html> <head lang"en"><meta http-equiv"Content-Type" content"text/html; charsetutf-8"><title>jQuery</title><style>…...
2024/4/21 4:25:28 - angular + ionic tba切换栏
tab 切换 可以在 HTML代码中 给导航行 加个点击事件 <ul><li (click)lisChange("1");lis!lis [ngClass]"{cls1: lis,cls2:!lis}">燃气统计</li><li (click)lisChange("2");lis2!lis2[ngClass]"{sls1: lis2,sls2:!li…...
2024/4/21 4:25:26 - fiddler无法抓取chrome解决方法
前端开发中,不可避免的要和服务器端进行联调,少了fiddler这个利器可不行。由于无线开发需要配置UA,我使用chrome进行访问,但是今儿一早过来,发现fiddler无法抓取chrome的请求了。 想想昨天对chrome进行的操作,我觉得问题应该出在代理的身上。实际上fiddler是可以抓chrome…...
2024/5/6 11:50:29
最新文章
- 使用poi生成word文件时,zip相关的报错
apache poi-检测到Zip Bomb解决方案_zip bomb detected! the file would exceed the max. -CSDN博客...
2024/5/9 5:59:54 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/5/7 10:36:02 - Python读取文件里内容
如果要读取一个文件里的内容是 # 文件名:db.txt 1 2 3 4代码如下 import requests f open("db.txt", mode"rb") content f.read() f.close()data content.decode(utf-8)# 存到 list 里 data_list data.split(\r\n) print(data_list)# 结果…...
2024/5/5 8:37:34 - 产品推荐 | 中科亿海微推出亿迅®A8000金融FPGA加速卡
01、产品概述 亿迅A8000金融加速卡,是中科亿海微联合金融证券领域的战略合作伙伴北京睿智融科,将可编程逻辑芯片与金融行业深度结合,通过可编程逻辑芯片对交易行情加速解码,实现低至纳秒级的解码引擎,端到端的处理时延…...
2024/5/9 3:34:56 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/8 6:01:22 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/7 9:45:25 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/5/4 23:54:56 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/9 4:20:59 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/5/4 23:54:56 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/5/4 23:55:05 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/5/4 23:54:56 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/5/7 11:36:39 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/5/4 23:54:56 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/6 1:40:42 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/5/4 23:54:56 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/5/8 20:48:49 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/5/7 9:26:26 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/5/4 23:54:56 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/8 19:33:07 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/5/5 8:13:33 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/5/8 20:38:49 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/5/4 23:54:58 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/6 21:42:42 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/5/4 23:54:56 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57