在本文中,我们将详细介绍一套代码小程序&Web&Native运行的探索02的各个方面,并为您提供关于小程序代码库的相关解答,同时,我们也将为您带来关于.NETWeb部件|Web部件管理器|Web部件区
在本文中,我们将详细介绍一套代码小程序&Web&Native运行的探索02的各个方面,并为您提供关于小程序代码库的相关解答,同时,我们也将为您带来关于.NET Web 部件 | Web 部件管理器 | Web 部件区、asp.net-web-api – System.Web.Routing.RouteCollection不包含“MapHttpRoute”的定义 – VS 2012,Web API、asp.net-web-api – Windows.Web.Http.HttpClient WEB API Windows身份验证、asp.net-web-api – 什么将WCF Web API中的HttpOperationHandler替换为ASP.NET Web API的有用知识。
本文目录一览:- 一套代码小程序&Web&Native运行的探索02(小程序代码库)
- .NET Web 部件 | Web 部件管理器 | Web 部件区
- asp.net-web-api – System.Web.Routing.RouteCollection不包含“MapHttpRoute”的定义 – VS 2012,Web API
- asp.net-web-api – Windows.Web.Http.HttpClient WEB API Windows身份验证
- asp.net-web-api – 什么将WCF Web API中的HttpOperationHandler替换为ASP.NET Web API
一套代码小程序&Web&Native运行的探索02(小程序代码库)
接上文:一套代码小程序&Web&Native运行的探索01,本文都是一些探索性为目的的研究学习,在最终版输出前,内中的内容可能会有点乱
参考:
https://github.com/fastCreator/MVVM
https://www.tangshuang.net/3756.html
https://www.cnblogs.com/kidney/p/8018226.html
经过之前的学习,发现Vue其实与小程序框架相识度比较高,业内也有mpvue这种还比较成熟的方案了,我们这边依旧不着急去研究成熟的框架,现在看看自己能做到什么程度,最近也真正的开始接触了一些Vue的东西,里面的代码真的非常不错,研究学习了下Vue的结构,发现其实跟我们要的很类似,这里想要尝试初步的方案:提供Html模板->解析Html模板,其实这里就是Vue里面Parse部分的逻辑,一小部分代码,这样有很多Vue的代码可以借鉴,也变相的学习Vue的源码,一举两得,于是我们速度开始今天的学习
首先,我们设置一个简单的目标:设置一段简单的小程序模板,当我们做完web版本后,他可以在小程序中运行
<view class="c-row search-line" data-flag="start" ontap="clickHandler">
<view class="c-span9 js-start search-line-txt">
{{name}}</view>
</view>
1 Page({
2 data: {
3 name: ''hello world''
4 },
5 clickHandler: function () {
6 this.setData({
7 name: ''叶小钗''
8 })
9 }
10 })
这里第一个关键便是将html模板转换为js代码,如果是之前我们直接会用这种代码:
1 _.template = function (text, data, settings) {
2 var render;
3 settings = _.defaults({}, settings, _.templateSettings);
4
5 // Combine delimiters into one regular expression via alternation.
6 var matcher = new RegExp([
7 (settings.escape || noMatch).source,
8 (settings.interpolate || noMatch).source,
9 (settings.evaluate || noMatch).source
10 ].join(''|'') + ''|$'', ''g'');
11
12 // Compile the template source, escaping string literals appropriately.
13 var index = 0;
14 var source = "__p+=''";
15 text.replace(matcher, function (match, escape, interpolate, evaluate, offset) {
16 source += text.slice(index, offset)
17 .replace(escaper, function (match) { return ''\\'' + escapes[match]; });
18
19 if (escape) {
20 source += "''+\n((__t=(" + escape + "))==null?'''':_.escape(__t))+\n''";
21 }
22 if (interpolate) {
23 source += "''+\n((__t=(" + interpolate + "))==null?'''':__t)+\n''";
24 }
25 if (evaluate) {
26 source += "'';\n" + evaluate + "\n__p+=''";
27 }
28 index = offset + match.length;
29 return match;
30 });
31 source += "'';\n";
32
33 // If a variable is not specified, place data values in local scope.
34 if (!settings.variable) source = ''with(obj||{}){\n'' + source + ''}\n'';
35
36 source = "var __t,__p='''',__j=Array.prototype.join," +
37 "print=function(){__p+=__j.call(arguments,'''');};\n" +
38 source + "return __p;\n";
39
40 try {
41 render = new Function(settings.variable || ''obj'', ''_'', source);
42 } catch (e) {
43 e.source = source;
44 throw e;
45 }
46
47 if (data) return render(data, _);
48 var template = function (data) {
49 return render.call(this, data, _);
50 };
51
52 // Provide the compiled function source as a convenience for precompilation.
53 template.source = ''function('' + (settings.variable || ''obj'') + ''){\n'' + source + ''}'';
54
55 return template;
56 };
将上述代码做字符串处理成字符串函数,然后将data传入,重新渲染即可。然而技术在变化,在进步。试想我们一个页面某个子节点文字发生了变化,全部重新渲染似乎不太划算,于是出现了虚拟DOM概念(React 导致其流行),他出现的意义就是之前我们使用jQuery操作10次dom的时候浏览器会操作10次,这里render过程中导致的坐标计算10次render tree的形成可能让页面变得越来越卡,而虚拟DOM能很好的解决这一切,所以这里我们就需要将我们模板中的代码首先转换为虚拟DOM,这里涉及到了复杂的解析过程
PS:回到最初Server渲染时代,每次点击就会导致一次服务器交互,并且重新渲染页面
Virtual DOM
我们做的第一步就是将模板html字符串转换为js对象,这个代码都不要说去实现,光是想想就知道里面必定会有大量的正则,大量的细节要处理,但我们的目标是一套代码多端运行,完全没(能力)必要在这种地方耗费时间,所以我们直接阅读这段代码:https://johnresig.com/blog/pure-javascript-html-parser/,稍作更改后,便可以得到以下代码:
1 /*
2 * Modified at https://github.com/blowsie/Pure-JavaScript-HTML5-Parser
3 */
4
5 // Regular Expressions for parsing tags and attributes
6 let startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:@][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:''[^'']*'')|[^>\s]+))?)*)\s*(\/?)>/,
7 endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/,
8 attr = /([a-zA-Z_:@][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:''((?:\\.|[^''])*)'')|([^>\s]+)))?/g
9
10 // Empty Elements - HTML 5
11 let empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr")
12
13 // Block Elements - HTML 5
14 let block = makeMap("a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video")
15
16 // Inline Elements - HTML 5
17 let inline = makeMap("abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var")
18
19 // Elements that you can, intentionally, leave open
20 // (and which close themselves)
21 let closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr")
22
23 // Attributes that have their values filled in disabled="disabled"
24 let fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected")
25
26 // Special Elements (can contain anything)
27 let special = makeMap("script,style")
28
29 function makeMap(str) {
30 var obj = {}, items = str.split(",");
31 for (var i = 0; i < items.length; i++)
32 obj[items[i]] = true;
33 return obj;
34 }
35
36 export default function HTMLParser(html, handler) {
37 var index, chars, match, stack = [], last = html;
38 stack.last = function () {
39 return this[this.length - 1];
40 };
41
42 while (html) {
43 chars = true;
44
45 // Make sure we''re not in a script or style element
46 if (!stack.last() || !special[stack.last()]) {
47
48 // Comment
49 if (html.indexOf("<!--") == 0) {
50 index = html.indexOf("-->");
51
52 if (index >= 0) {
53 if (handler.comment)
54 handler.comment(html.substring(4, index));
55 html = html.substring(index + 3);
56 chars = false;
57 }
58
59 // end tag
60 } else if (html.indexOf("</") == 0) {
61 match = html.match(endTag);
62
63 if (match) {
64 html = html.substring(match[0].length);
65 match[0].replace(endTag, parseEndTag);
66 chars = false;
67 }
68
69 // start tag
70 } else if (html.indexOf("<") == 0) {
71 match = html.match(startTag);
72
73 if (match) {
74 html = html.substring(match[0].length);
75 match[0].replace(startTag, parseStartTag);
76 chars = false;
77 }
78 }
79
80 if (chars) {
81 index = html.indexOf("<");
82
83 var text = index < 0 ? html : html.substring(0, index);
84 html = index < 0 ? "" : html.substring(index);
85
86 if (handler.chars)
87 handler.chars(text);
88 }
89
90 } else {
91 html = html.replace(new RegExp("([\\s\\S]*?)<\/" + stack.last() + "[^>]*>"), function (all, text) {
92 text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, "$1$2");
93 if (handler.chars)
94 handler.chars(text);
95
96 return "";
97 });
98
99 parseEndTag("", stack.last());
100 }
101
102 if (html == last)
103 throw "Parse Error: " + html;
104 last = html;
105 }
106
107 // Clean up any remaining tags
108 parseEndTag();
109
110 function parseStartTag(tag, tagName, rest, unary) {
111 tagName = tagName.toLowerCase();
112
113 if (block[tagName]) {
114 while (stack.last() && inline[stack.last()]) {
115 parseEndTag("", stack.last());
116 }
117 }
118
119 if (closeSelf[tagName] && stack.last() == tagName) {
120 parseEndTag("", tagName);
121 }
122
123 unary = empty[tagName] || !!unary;
124
125 if (!unary)
126 stack.push(tagName);
127
128 if (handler.start) {
129 var attrs = [];
130
131 rest.replace(attr, function (match, name) {
132 var value = arguments[2] ? arguments[2] :
133 arguments[3] ? arguments[3] :
134 arguments[4] ? arguments[4] :
135 fillAttrs[name] ? name : "";
136
137 attrs.push({
138 name: name,
139 value: value,
140 escaped: value.replace(/(^|[^\\])"/g, ''$1\\\"'') //"
141 });
142 });
143
144 if (handler.start)
145 handler.start(tagName, attrs, unary);
146 }
147 }
148
149 function parseEndTag(tag, tagName) {
150 // If no tag name is provided, clean shop
151 if (!tagName)
152 var pos = 0;
153
154 // Find the closest opened tag of the same type
155 else
156 for (var pos = stack.length - 1; pos >= 0; pos--)
157 if (stack[pos] == tagName)
158 break;
159
160 if (pos >= 0) {
161 // Close all the open elements, up the stack
162 for (var i = stack.length - 1; i >= pos; i--)
163 if (handler.end)
164 handler.end(stack[i]);
165
166 // Remove the open elements from the stack
167 stack.length = pos;
168 }
169 }
170 };
这是一段非常牛逼的代码,要写出这种代码需要花很多功夫,绕过很多细节,自己写很难还未必写得好,所以拿来用就好,不必愧疚......,但是我们需要知道这段代码干了什么:
他会遍历我们的字符串模板,解析后会有四个回调可供使用:start、end、chars、comment,我们要做的就是填充里面的事件,完成我们将HTML转换为js对象的工作:
1 <!doctype html>
2 <html>
3 <head>
4 <title>起步</title>
5 </head>
6 <body>
7
8 <script type="module">
9
10 import HTMLParser from ''./src/core/parser/html-parser.js''
11
12 let html = `
13 <div class="c-row search-line" data-flag="start" ontap="clickHandler">
14 <div class="c-span9 js-start search-line-txt">
15 {{name}}</div>
16 </div>
17 `
18
19 function arrToObj(arr) {
20 let map = {};
21 for(let i = 0, l = arr.length; i < l; i++) {
22 map[arr[i].name] = arr[i].value
23 }
24 return map;
25 }
26
27 //存储所有节点
28 let nodes = [];
29
30 //记录当前节点位置,方便定位parent节点
31 let stack = [];
32
33 HTMLParser(html, {
34 /*
35 unary: 是不是自闭和标签比如 <br/> input
36 attrs为属性的数组
37 */
38 start: function( tag, attrs, unary ) { //标签开始
39 /*
40 stack记录的父节点,如果节点长度大于1,一定具有父节点
41 */
42 let parent = stack.length ? stack[stack.length - 1] : null;
43
44 //最终形成的node对象
45 let node = {
46 //1标签, 2需要解析的表达式, 3 纯文本
47 type: 1,
48 tag: tag,
49 attrs: arrToObj(attrs),
50 parent: parent,
51 //关键属性
52 children: [],
53 text: null
54 };
55
56 //如果存在父节点,也标志下这个属于其子节点
57 if(parent) {
58 parent.children.push(node);
59 }
60 //还需要处理<br/> <input>这种非闭合标签
61 //...
62
63 //进入节点堆栈,当遇到弹出标签时候弹出
64 stack.push(node)
65 nodes.push(node);
66
67 debugger;
68 },
69 end: function( tag ) { //标签结束
70 //弹出当前子节点,根节点一定是最后弹出去的,兄弟节点之间会按顺序弹出,其父节点在最后一个子节点弹出后会被弹出
71 stack.pop();
72 debugger;
73 },
74 chars: function( text ) { //文本
75 //如果是空格之类的不予处理
76 if(text.trim() === '''') return;
77 let node = nodes[nodes.length - 1];
78 //如果这里是表达式{{}}需要特殊处理
79 if(node) node.text = text.trim()
80 debugger;
81 }
82 });
83
84 console.log(nodes)
85
86 </script>
87
88 </body>
89 </html>
这里输出了我们想要的结构:
第一个节点便是跟节点,我们可以根据他遍历整个节点,我们也可以根据数组(里面有对应的parent关系)生成我们想要的结构,可以看出借助强大的第三方工具库可以让我们的工作变得更加高效以及不容易出错,如果我们自己写上述HTMLParser会比较困难的,什么时候需要自己写什么时候需要借助,就要看你要做那个事情有没有现成确实可用的工具库了,第二步我们尝试下将这些模板标签,与data结合转换为真正的HTML结构
简单的Virtual DOM TO HTML
这里需要data加入了,我们简单实现一个MVVM的类,并且将上述Parser做成一个方法:
1 <!doctype html>
2 <html>
3 <head>
4 <title>起步</title>
5 </head>
6 <body>
7
8 <div id="app">
9
10 </div>
11
12 <script type="module">
13
14 import HTMLParser from ''./src/core/parser/html-parser.js''
15
16 let html = `
17 <div class="c-row search-line" data-flag="start" ontap="clickHandler">
18 <div class="c-span9 js-start search-line-txt">
19 {{name}}</div>
20 <input type="text">
21 <br>
22 </div>
23 `
24
25 function arrToObj(arr) {
26 let map = {};
27 for(let i = 0, l = arr.length; i < l; i++) {
28 map[arr[i].name] = arr[i].value
29 }
30 return map;
31 }
32
33 function htmlParser(html) {
34
35 //存储所有节点
36 let nodes = [];
37
38 //记录当前节点位置,方便定位parent节点
39 let stack = [];
40
41 HTMLParser(html, {
42 /*
43 unary: 是不是自闭和标签比如 <br/> input
44 attrs为属性的数组
45 */
46 start: function( tag, attrs, unary ) { //标签开始
47 /*
48 stack记录的父节点,如果节点长度大于1,一定具有父节点
49 */
50 let parent = stack.length ? stack[stack.length - 1] : null;
51
52 //最终形成的node对象
53 let node = {
54 //1标签, 2需要解析的表达式, 3 纯文本
55 type: 1,
56 tag: tag,
57 attrs: arrToObj(attrs),
58 parent: parent,
59 //关键属性
60 children: []
61 };
62
63 //如果存在父节点,也标志下这个属于其子节点
64 if(parent) {
65 parent.children.push(node);
66 }
67 //还需要处理<br/> <input>这种非闭合标签
68 //...
69
70 //进入节点堆栈,当遇到弹出标签时候弹出
71 stack.push(node)
72 nodes.push(node);
73
74 // debugger;
75 },
76 end: function( tag ) { //标签结束
77 //弹出当前子节点,根节点一定是最后弹出去的,兄弟节点之间会按顺序弹出,其父节点在最后一个子节点弹出后会被弹出
78 stack.pop();
79
80 // debugger;
81 },
82 chars: function( text ) { //文本
83 //如果是空格之类的不予处理
84 if(text.trim() === '''') return;
85 text = text.trim();
86
87 //匹配 {{}} 拿出表达式
88 let reg = /\{\{(.*)\}\}/;
89 let node = nodes[nodes.length - 1];
90 //如果这里是表达式{{}}需要特殊处理
91 if(!node) return;
92
93 if(reg.test(text)) {
94 node.children.push({
95 type: 2,
96 expression: RegExp.$1,
97 text: text
98 });
99 } else {
100 node.children.push({
101 type: 3,
102 text: text
103 });
104 }
105 // debugger;
106 }
107 });
108
109 return nodes;
110
111 }
112
113 class MVVM {
114 /*
115 暂时要求必须传入data以及el,其他事件什么的不管
116
117 */
118 constructor(opts) {
119
120 //要求必须存在,这里不做参数校验了
121 this.$el = typeof opts.el === ''string'' ? document.getElementById(opts.el) : opts.el;
122
123 //data必须存在,其他不做要求
124 this.$data = opts.data;
125
126 //模板必须存在
127 this.$template = opts.template;
128
129 //存放解析结束的虚拟dom
130 this.$nodes = [];
131
132 //将模板解析后,转换为一个函数
133 this.$initRender();
134
135 //渲染之
136 this.$render();
137 debugger;
138 }
139
140 $initRender() {
141 let template = this.$template;
142 let nodes = htmlParser(template);
143 this.$nodes = nodes;
144 }
145
146 //解析模板生成的函数,将最总html结构渲染出来
147 $render() {
148
149 let data = this.$data;
150 let root = this.$nodes[0];
151 let parent = this._createEl(root);
152 //简单遍历即可
153
154 this._render(parent, root.children);
155
156 this.$el.appendChild(parent);
157 }
158
159 _createEl(node) {
160 let data = this.$data;
161
162 let el = document.createElement(node.tag || ''span'');
163
164 for (let key in node.attrs) {
165 el.setAttribute(key, node.attrs[key])
166 }
167
168 if(node.type === 2) {
169 el.innerText = data[node.expression];
170 } else if(node.type === 3) {
171 el.innerText = node.text;
172 }
173
174 return el;
175 }
176 _render(parent, children) {
177 let child = null;
178 for(let i = 0, len = children.length; i < len; i++) {
179 child = this._createEl(children[i]);
180 parent.append(child);
181 if(children[i].children) this._render(child, children[i].children);
182 }
183 }
184
185
186 }
187
188
189 let vm = new MVVM({
190 el: ''app'',
191 template: html,
192 data: {
193 name: ''叶小钗''
194 }
195 })
196
197
198
199
200 </script>
201
202 </body>
203 </html>
1 <div class="c-row search-line" data-flag="start" ontap="clickHandler">
<div class="c-span9 js-start search-line-txt"><span>叶小钗</span></div>
<input type="text">
</div>
这个代码非常简陋,只是对text部分做了处理,没有对属性,style等做处理,但是越是功能简单的代码理解起来越容易,后续的style以及属性大同小异,我们这里开始处理,介于篇幅,下次继续
.NET Web 部件 | Web 部件管理器 | Web 部件区
如何解决.NET Web 部件 | Web 部件管理器 | Web 部件区
我在 ASP.NET Web 窗体中使用 Web 部件。我的项目运行正常。 但是,当我拖放 Web 部件管理器时出现此错误,谁能指导我如何在 Windows 10 中解决此问题。
与 sql Server 建立连接时发生与网络相关或特定于实例的错误。服务器未找到或无法访问。验证实例名称是否正确以及 sql Server 是否配置为允许远程连接。 (提供程序:sql 网络接口,错误:26 - 错误定位服务器/指定的实例)
asp.net-web-api – System.Web.Routing.RouteCollection不包含“MapHttpRoute”的定义 – VS 2012,Web API
我已经用Web API创建了一个新的MVC 4应用程序。基于一些示例和教程,我开始配置我的路由:
routes.MapHttpRoute( name: "Controller only",routeTemplate: "api/{controller}" );
但是,这会导致RouteCollection不包含MapHttpRoute的定义的错误。我是否安装了一些DLL?
据我看到,我已经安装了所有正确的DLL和版本。
解决方法
asp.net-web-api – Windows.Web.Http.HttpClient WEB API Windows身份验证
使用(Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient())
{
//添加用户代理标头
var headers = httpClient.DefaultRequestHeaders;
//检查用户标头值的安全方法是TryParseAdd方法
//因为我们知道这个标题是可以的,所以我们使用ParseAdd会抛出异常
//值不好 – http://msdn.microsoft.com/en-us/library/windows/apps/dn440594.aspx
headers.UserAgent.ParseAdd("ie"); headers.UserAgent.ParseAdd("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"); using (var response = await httpClient.GetAsync(new Uri(url)))
我没有看到发送默认凭据的方法.
解决方法
Windows.Web.Http.Filters.HttpBaseProtocolFilter filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter(); filter.AllowUI = false; HttpClient client = new HttpClient(filter); Uri uri = new Uri("http://localhost/?basic=1"); var response = await client.GetAsync(uri); System.Diagnostics.Debug.WriteLine(response);
你需要凭证吗?使用HttpBaseProtocolFilter.ServerCredential.试试这个:
Uri uri = new Uri("http://localhost?ntlm=1"); Windows.Web.Http.Filters.HttpBaseProtocolFilter filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter(); filter.AllowUI = false; // Set credentials that will be sent to the server. filter.ServerCredential = new Windows.Security.Credentials.PasswordCredential( uri.ToString(),"userName","abracadabra"); HttpClient client = new HttpClient(filter); var response = await client.GetAsync(uri); System.Diagnostics.Debug.WriteLine(response);
您需要默认的Windows凭据(域凭据)吗?只需将Enterprise Authentication功能添加到Package.appxmanifest即可.
asp.net-web-api – 什么将WCF Web API中的HttpOperationHandler替换为ASP.NET Web API
解决方法
以下是一些您可能会觉得有用的链接:
> How to Migrate from WCF Web API to ASP.NET Web API
> Mike的博客于How WebAPI does Parameter Binding年
> ASP.NET WebAPI页面上的> Getting started tutorials.
希望这可以帮助.
关于一套代码小程序&Web&Native运行的探索02和小程序代码库的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于.NET Web 部件 | Web 部件管理器 | Web 部件区、asp.net-web-api – System.Web.Routing.RouteCollection不包含“MapHttpRoute”的定义 – VS 2012,Web API、asp.net-web-api – Windows.Web.Http.HttpClient WEB API Windows身份验证、asp.net-web-api – 什么将WCF Web API中的HttpOperationHandler替换为ASP.NET Web API的相关知识,请在本站寻找。
本文标签: