Giter Site home page Giter Site logo

article's People

Contributors

yuiitsu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

article's Issues

一起来做Chrome/Firefox Extension《本地存储localStorage》

一起来做chrome Extension《本地存储localStorage》

chrome中的本地存储其实也是用的HTML5中localStorage,唯一区别是chrome扩展有自己的localStorage,它属于这个扩展,而不属于一个域名。得用这一点可以很好的处理扩展自己的一些数据,而不受访问网站和域名的影响。

localStorage基础

localStorage是HTML5特性,所以有些浏览器不一定支持,不过我们这里讲的是chrome扩展,所以完全不用担心这个问题。如果想在WEB页面上使用,那就要检查一下是不是支持它

可以这样的检测:

if(window.localStorage){
	console.log('支持');
}else{
	console.log('不支持');
}

localStorage和memcache一样,是key/value的存储类型,所以,除非你只存字符串,不然就得以json的形式来存储。之后解析成数组,就可以很好的使用里面的值。

增删改查:

// 存储/修改
localStorage.name = 'only';
localStorage['name'] = 'only';

// 删除
localStorage['name'] = null; 删除一个
localStorage.clear(); 删除所有

// 查
var name = localStorage.name;
var name = localStorage['name'];

localStorage是不能跨域的,所以不同域名的localStorage是互不干扰的。比如在jgb.com上存储了一个值,在www.jgb.com是访问不了它的,反之亦然。

chrome扩展中的localStorage

扩展中的localStorage没什么不同,只是有一个注意点,content_script中的localStorage是存储在对应域名下的,所以别的域名是不能访问的。background_script中的localStorage是存储在chrome扩展下的,所以不管什么域名都可以访问它。这一点很重要,如果没有这个特性,扩展的应用场景就会少很多很多。

查看localStorage

查看对应域名的localStorage

右键选择审查元素,如图选择

image

查看扩展的localStorage

打开扩展界面,打开你扩展的背景页

image

如图选择

image

简单示例

这个示例很简单,扩展将匹配www.jgb.cn和www.amazon.com,打开两个网站后,会在页面中间显示一个列表和一个表单,列表是以前填入的名字,表单可以填入你名字另外的名字。列表里,可以删除一条,也可以删除所有名字。简单也讲,就是一个增删查。在这个例子中,可以看到,在www.jgb.cn和www.amazon.com中都是可以读取和操作这些存储内容的,不受域名的限制。

第一步:建立文件夹

目录名就叫localstorage,目录中的结构基本如图:

image

里面除了mainfest.json是必须的,其它东西都可以按自己的习惯来

第二步:建立mainfest.json文件

之前的日志已经讲过这个文件,所以这里就直接帖内容

{
	"manifest_version": 2,
	"name": "一起来做chrome扩展之本地存储",
	"version": "0.1",
	"description": "一个简单的本地存储例子",
	"background": {
		"scripts": [
			"include/jquery-1.11.0.min.js",	
			"scripts/background.js"
		]
	},
	"content_scripts": [{
		"matches": [
			"http://*.jgb.cn/*",
			"http://*.amazon.com/*"
		],
		"css": ["css/common.css"],
		"js": [
			"include/jquery-1.11.0.min.js",
			"scripts/main.js"
		]
	}]
}

如果对这个文件不熟悉,可以看看一起来做chrome扩展《基础介绍》

把jquery拷贝到include中,再到scripts目录建立main.js和background.js

第三步:创建界面

这里我们创建一个简单的界面,在目标网站的正中间,显示一个500*300的浮动层,正常js,写法随意

var main = {
	
	/**
	 * 创建界面
	 */
	createHtml: function(){
		var _html = '<div id="ls_box">'+
			'<h3>'+
				'本地存储 local storage'+
			'</h3>'+
			'<div id="ls_list">'+
				'正在加载数据...'+
			'</div>'+
			'<div id="ls_form">'+
				'<label>'+
					'新增: '+
				'</label>'+
				'<input type="text" id="ls_message" />'+
				'<button id="ls_save">保存</button>'+
			'</div>'+
		'</div>';
		$('body').append(_html);
	}
}

界面大致如下

image

第四步:向background发送消息

方法很简单

/**
 * 向background发送消息
 * @params strAction string 执行方法
 * @params dicData dict 数据字典
 * @params callback function 回调函数
 */
sendMessageBack: function(strAction, dicData, callback){
	chrome.extension.sendMessage({'action': strAction, 'data': dicData}, callback);
},

第五步:将存储内容输出到页面

/**
 * 将已有数据写到页面上
 */
showList: function(dicList){
	if(!dicList || dicList.length == 0){
		$("#ls_list").html('<p>没有找到数据</p>');
		return;
	}

	// 遍历对象,构建输出html
	var _html = ['<ul>'];
	for(var i in dicList){
		_html.push('<li><span class="ls_del" data-item="'+dicList[i]+'">X</span>'+dicList[i]+'</li>');
	}
	_html.push('</ul>');
	$("#ls_list").html(_html.join(''));

	// 监听删除
	_this.listenDel();
},

第六步:监听保存

一个简单的单击事件,把文本内容发送给background.js,然后将返回的数据利用上面的方法输出到页面上

/**
 * 监听保存事件
 */
listenSave: function(){
	_this = this;

	$("#ls_save").click(function(){
		// 获取message
		var strMessage = $.trim($('#ls_message').val());
		if(!strMessage){
			return false;
		}
		// 通知background,保存数据
		_this.sendMessageBack('save', {'message': strMessage}, function(response){
			if(response.status == 200){
				// 将内容输出到页面
				_this.showList(response.data);
				$('#ls_message').val('');
			}
		});
	});
},

第七步:监听删除

删除和保存同理,只是发送到background的请求方法不同,正常JS操作,这里就不帖代码,最后看看background.js的监听与返回消息

第八步:background监听消息与返回

/**
 * 监听content_script发送的消息
 */
chrome.extension.onMessage.addListener(function(request, _, sendResponse){
	// 返回数据
	var dicReturn;

	// 读取已存数据
	if(request.action == 'list'){
		// 从localstorage中读取数据
		var strList = localStorage['list'];
		if(strList){
			// 将json字符串转为对象
			var dicList = JSON.parse(strList)
			dicReturn = {'status': 200, 'data': dicList}
		}else{
			dicReturn = {'status': 404}
		}

		// 向content_script返回信息
		sendResponse(dicReturn);
	}

	// 保存
	if(request.action == 'save'){
		// content_script传来message
		var strMessage = request.data.message;
		// 从localstorage中读取数据
		var strList = localStorage['list'];
		var dicList = [];
		if(strList){
			// 将json字符串转为对象
			dicList = JSON.parse(strList)
		}
		dicList.push(strMessage);
		localStorage['list'] = JSON.stringify(dicList);

		dicReturn = {'status': 200, 'data': dicList};
		// 向content_script返回信息
		sendResponse(dicReturn);
	}

	// 删除
	if(request.action == 'del'){
		// content_script传来的message
		var strMessage = request.data.message;
		// 从localstorage中读取数据
		var strList = localStorage['list'];
		if(strList){
			// 将json字符串转为对象
			dicList = JSON.parse(strList);
			// 遍历数据,找到对应值
			for(var i in dicList){
				if(dicList[i] == strMessage){
					// 删除该值
					dicList.splice(i, 1);
				}
			}

			// 重新存储
			localStorage['list'] = JSON.stringify(dicList);
			// 向content_script返回信息
			sendResponse({'status': 200});
		}else{
			sendResponse({'status': 501, 'msg': '删除失败,未有数据'});
		}
	}
})

接收content_script发来的数据,使用request.data.message,data.message都是自己定义的key,所以想传什么,都可以自己定

返回值使用sendResponse()方法,内容为一个对象,content_script接受到后,可以直接使用,所以就有了if(response.status == 200){}这样的写法。

一个简单的本地存储就是这样了,加载到chrome或是同一内核的浏览器中,打开www.jgb.cn或是www.amazon.com,就可以看到扩展界面,保存一些数据,在两个网站刷新,会发现,数据都是可以获取的。

源代码

本示例代码:https://github.com/onlyfu/localstorage

一起来做Chrome/Firefox Extension《AJAX请求》

一起来做chrome Extension《AJAX请求》

chrome在一次更新之后,出于安全考虑,完全的禁止了content_script从https向http发起ajax请求,即使正常情况下也会在console里给出提示。这对于WEB来讲是好事,但对于扩展来讲就是坏事。平时可以很容易的请求数据,现在就没那么容易了。好在chrome还提供了background_script,利用content_script和background_script之前的通信来实现ajax的请求,就跳过了chrome的这一限制。

content_script

从名字里就知道,content_script是植入型的,它会被植入到符合匹配的网站页面上。在页面加载完成后执行。content_script最有用的地方是操作网站页面上的DOM。一切平时做前端的一些操作它都可以做,像什么添加、修改、删除DOM,获取DOM值,监听事件等等,都可以很容易的做到。所以,如果想获取人家的登录帐户和密码,就是件非常容易的事,只需要添加content_script,监听帐户和密码的文本框,获得值后将数据发送到自己的服务器就可以了。因此,特别说明,别乱装扩展,特别是不从官方扩展库里下载的扩展。

使用content_script

要使用content_script,需要在manifest.json中配置,如下:

{
	"manifest_version": 2,
	"name": "My Extension",
	"description": "Extension description",
	"version": "1.0",

	"content_scripts": {
		"js": [
			"content.js"
		]
	}
}

这样,在页面加载完成后,就会加载content.js,在content.js里,就可以控制页面元素。如果要在content.js中使用jquery,需要将jquery文件加到content.js前面,如:

content_script使用jquery

{
	"content_scripts": {
		"js": [
			"jquery.js",
			"content.js"
		]
	}
}

除了可以加载js,content_scripts里还可以加载CSS文件,这样可以让你的扩展漂亮一点,如:

content_script使用CSS

{
	"content_scripts": {
		"js": [
			"content.js"
		],
		"css": ["style.css"]
	}
}

在content_scripts中,还有一项重要的设置就是matches,它是用来配置,符合扩展使用的网址,如:我只想这个扩展在打开www.jgb.cn时才启用,那么matches就要这样写:

设置匹配网站

{
	"content_scripts": {
		"js": [
			"content.js"
		],
		"css": ["style.css"]
	},
	"matches": [
		"http://*.jgb.cn/*"
	]
}

如果还要匹配www.amazon.com,那就加上:

{
	"matches": [
		"http://*.jgb.cn/*",
		"http://*.amazon.com/*"
	]
}

注意,http只适用于http,像amazon.com这样的站即有http也有https,所以得把https也加上,如下:

{
	"matches": [
		"http://*.jgb.cn/*",
		"http://*.amazon.com/*",
		"https://*.amazon.com/*"
	]
}

background_script

它在chrome扩展启动的时候就启动了,做着它的事,而且等待着你给他的指令。它没办法控制页面元素,但可以通过content_script告诉它。ajax同理,如果要在页面打开时向别的服务器请求数据,这时就可以告诉background_script,让它去请求,然后把返回的数据发送给content_script。这样就不会受到浏览器的安全限制影响。

使用background_script

要使用background_script,需要在manifest.json中配置,如下:

{
	"manifest_version": 2,
	"name": "My Extension",
	"description": "Extension description",
	"version": "1.0",

	"background": {
		"scripts": [
			"background.js"
		]
	}
}

使用jquery和content_scripts同理,需要把jquery文件加到background.js前面,如:

在background_script中使用jquery

{
	"background": {
		"scripts": [
			"jquery.js",
			"background.js"
		]
	}
}

跨域

默认情况下Ajax是不允许跨域的,但扩展提供了跨域的配置,在前一篇《基础介绍》中提到过,那就是permissions,它除了可以让扩展使用chrome的一些功能外,还可以允许JS实现对目录网站的跨域访问,如:

{
	"permissions": [
		"http://www.jgb.cn/" // 允许跨域访问www.jgb.cn
	]
}

有了以上的配置,这时候就可以来看看怎样通过background_scripts来实现Ajax请求了。

向background发送请求

在content_script中向background_script发送请求有好几种方式,这里只列出我常的一种,应该来讲,能满足大多数情况的使用,其它方法,请查询文档,方法如下:

chrome.extension.sendMessage({}, callBack);

sendMessage()方法,它有两个参数,第一个要发送的数据,就像post请求一样,第二个是回调函数。如在content_script中,点击一个按钮,将一个字符串发送到background_script

$(function(){
	$("#button").click(function(){
		chrome.extension.sendMessage({'txt': '这里是发送的内容'}, function(d){
			console.log(d); // 将返回信息打印到控制台里
		});
	});
})

在background中监听content请求

在background中监听content请求,使用chrome.extension.onMessage.addListener(),示例如下:

chrome.extension.onMessage.addListener(function(objRequest, _, sendResponse){});

objRequest,即为请求的参数,在上一个例子就是{'txt': '这里是发送的内容'},可以通过objRequest.txt来获取内容。其实就是一个字典。

sendResponse,为返回值方法,可以将数据返回给content_script,那么一个简单的例子就是:

chrome.extension.onMessage.addListener(function(objRequest, _, sendResponse){
	var strText = objRequest.txt;
	// 将信息能过Ajax发送到服务器
	$.ajax({
		url: 'http://www.jgb.cn/',
		type: 'POST',
		data: {'txt': strText},
		dataType: 'json',
	}).then(function(){
		// 将正确信息返回content_script
		sendResponse({'status': 200});
	}, function(){
		// 将错误信息返回content_script
		sendResponse({'status': 500});
	});
});

这样一去一来,也就实现content_script向background_script发送请求,并使用background_script执行ajax请求的目的,非常的简单好用

在此基础上,增加一些条件和数据,就可以很好的实现接收,发送数据的操作。比如向自己的服务器请求或发送数据。

通过修改chrome启动参数,实现可在https页面向http页面发起ajax请求

除了使用background_script来发起Ajax请求外,还可以通过修改chrome的启动参数来达到这个目的。参数为:--allow-running-insecure-content,操作方法:

  1. 右键chrome快捷方式,选择属性
  2. 在目标的最后,输入--allow-running-insecure-content,中间有个空格

这样chrome就可以允许你在https页面向http发起ajax请求了。这个方法可以达到目的,但不推荐,因为不科学。

一起来做Chrome/Firefox Extension《一些问题》

一起来做Chrome/Firefox Extension《一些问题》

更新时间 说明
2019.4.16 增加:关于chrome.tabs.getCurrent()

目录

  1. Unchecked runtime.lastError: The message port closed before a response wa received.
  2. 使用 eval
  3. Content script注入iframe
    1. Extenstion内的html
    2. 站外连接
  4. 关于chrome.tabs.getCurrent()

1. Unchecked runtime.lastError: The message port closed before a response wa received.

此错误一般发生在background js和content js通讯的时候,问题描述得也非常清楚,解决方法非常简单,即在收到消息后,在同步时间里send respnose就可以了。

注意:send response如果在异步方法里,并不能解决这个问题。

// Example:
// background js 或content js
chrome.extension.onMessage.addListener(function(request, _, sendResponse) {
    sendResponse('');
});

2. 使用eval

Chrome Extension默认是禁止使用eval方法的,使用之前,需要先在manifest.json里开启,如下:

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

3. 使用iframe

注入iframe同样受content_security_policy限制,而且会受到目标站点的content_security_policy限制。关于content_security_policy内容比较多,这里分成两种情况

3.1 Extension内的html

注入的iframe加载Extension内的html稍微没有这么麻烦,只需要在manifest.json里指定要加载的html就好了

"web_accessible_resources": ["example.html"]

注入iframe的src,可以使用chrome.runtime.getUrl()来获取地址

let src = chrome.runtime.getURL('example.html')

注:要注入网站的content_security_policy对这样的iframe注入会不会有影响,目前还没有测试到。

此方法在 Fika (reader-mode) 扩展里有使用

3.2 站外连接

如上所说,注入iframe是受目标网站的content_security_policy限制的,所以,如果目标网站不允许,你的注入将会失败,如medium.com的content_security_policy关于frame-src的部分:

default-src 'self';

...

frame-src chromenull: https: webviewprogressproxy: medium: 'self';

...

它允许了https的地址,所以,注入的iframe加载https地址是没有问题的,而http的地址将被拒绝。因为注入已经离开了Chrome Extenstion的范围,所以,不管你怎么对Chrome Extension的content_security_policy进行设置并不会有用。

关于content_security_policy,可以看 https://www.html5rocks.com/en/tutorials/security/content-security-policy/

4.关于chrome.tabs.getCurrent()

首先看看官方文档说明

Gets the tab that this script call is being made from. May be undefined if called from a non-tab context (for example, a background page or popup view).

可以看到,它只说无法在没有tab的context里得到,如background page和popup,正常人都会觉得它可以在content script里使用,但其实chrome.tabs API只能在background page和extension单独页面里使用,content script是不能使用chrome.tabs API的,所以getCurrent()是只能在textension单独页面里使用的。

那么如果想要打开了个未激活的tab时做一些操作browser icon的操作时,如果正确的获取脚本运行页面的tab id呢?如:右键链接在新Tab里打开,chrome会新开了一个tab打开页面,但这个tab并未激活(激活指点击tab,这这个tab处于浏览器的活动界面里)。

我在这里做两件事:

  1. 监听tab的激活事件,激活时往content script发消息
  2. content script接到消息检查自己的状态对象,如果OK给background发消息,通知它处理browser icon的变化。
chrome.tabs.onActivated.addListener(function(activeInfo) {
	let tabId = activeInfo.tabId;
	// 给对应tabId的content script发消息
});

问题:

当onActivated解法的时候,如果当前页面没有content script注入接受并返回response,就会报一个接受方法不存在的错误。如打开扩展管理界面。好在并不会有什么影响,扩展发布后,也不会有这个报错。

所以,其实最好是能在content script里使用chrome.tabs.getCurrent()API来处理这类事情。

一起来做Chrome/Firefox Extension《页面右键菜单》

一起来做Chrome Extension《页面右键菜单》


本文主要内容

  • contextMenus的设置
    • 打开权限
    • 创建菜单
    • 点击菜单
  • background script向content script发送消息

预览

WechatIMG2.png

1. contextMenus的设置

1.1 打开权限

contextMenus同其它功能一样,都需要在permissions里指定开启,所以非常简单,在项目的manifest.json文件的permissions中加上contextMenus

"permissions": [
    "contextMenus"
]

这样就可以在background script里使用contextMenus了

1.2 创建右键菜单

首先需要明确,创建菜单以及菜单的事件都是由background script操作的,不是content script,不要被菜单在页面上的现象蒙蔽了。所以,在manifest.json里,一定要配置background scripts(这是重点,勾上,要考)

在background script里,创建菜单代码:

chrome.contextMenus.create({
    type: 'normal',
    title: 'Menu Demo',
    id: 'menuDemo',
    contexts: ['all'],
    onclick: genericOnClick
}, function () {
    console.log('contextMenus are create.');
});

create方法第一个参数是菜单信息对象,具体可以查看:https://developer.chrome.com/extensions/contextMenus

PS: type为separator时,目前版本并不会生效,菜单会直接变成子集菜单的形式,应该是一个bug,在论坛上2010年时有人提过,现在还存在,不知道是为什么

这里主要提的是title,id,onclick

title: 很显示就是menu的名字
id: 当然就是它的ID,点击后要判断点的是谁,就得靠它了,所以名字好好取
onclick: 点击事件,跟的就是处理的方法名,如genericOnClick,就是对应的一个function

1.3 点击菜单

使用create参数的onclick或是监听事件方法都可以对菜单的点击事件进行监听,它们的回调函数都会带两个参数,info和tabs

function genericOnClick(info, tab) {
    // do something.
}

info 是一个字典数据,包含页面及菜单的一些信息,以及在页面上选中的内容文本

{
    editable: false
    frameId: 0
    menuItemId: "menuDemo"
    pageUrl: "https://www.colorgamer.com/"
    selectionText: "colorgamer"
}

信息一目了然

tab 同样是一个字典,包含页面比较具体的一些信息,如tab id等信息,页面宽度等,具体可以自行查看,这里我们将用到tab的id。

那么菜单有了,事件也有了,接下来的问题就是,通过contextMenus拿到的信息,执行的操作都是在background script里的,那如何传回content script里呢?因为很多事情还是要在页面上处理,而不是后台处理。

在前面一篇一起来做chrome扩展《AJAX请求》,我们说过content script如果向background script发送消息,其实倒过来也是成立的,只是有一点(重点,要考)

每个extension的后台都只有一个,而tab有无数个,所以,每个tab向background script发送消息不需要指定什么就能送达,而倒过来后,background script要向哪个tab发送消息呢?

很明显,我们要告诉它,它才会知道,所以这里分两步

  1. 获取当前活动中的tab,因为活动中的就是你看的
  2. 向这个tab发送消息
// 向该tab发送消息
chrome.tabs.sendMessage(tab.id, {'contextMenuId': info.menuItemId, 'info': info}, function(response) {});

发送消息,之前我们使用的是chrome.extension.sendMessage,这里使用chrome.tabs.sendMessage,很明显,是向指定的tab发送,sendMessage方法有三个参数

  • 第一个参数是tab的ID
  • 第二个参数是发送的数据对象
  • 第三个就是回调函数了,有什么要传回来的,都是通过它进行

content script接收消息和之前一样

chrome.extension.onMessage.addListener(function(request, _, response) {
    console.log(request);
});

request即是sendMessage的第二个参数的数据对象,response当然就是回调函数了。

好了,关于Chrome Extension的contextMenus的使用就这些内容,关于contextMenus更多的信息可以参考官方文档。

谢谢您的阅读,有任何问题都可以联系我。

一起来做Chrome/Firefox/Edge Extension《使用eval类方法》

一起来做Chrome/Firefox/Edge Extension《使用eval类方法》

因为FireFox已经使用了Chrome相同的Extension内核,所以为Chrome制作的Extension可以几乎无缝的发布到FireFox里。但Firefox对代码的要求比Chrome要高,比如今天的主角eval类方法就不允许在Extension里使用,Chrome是可以使用的。本文就是介绍一下相关的内容以及如何去支持。

eval类方法

简单说明一下,eval类方法,除了eval还有new Function,这两个方法要在Extension里使用,需要在manifest.json里开启安全策略,如:

"content_security_policy": "'unsafe-eval'",

不然就会报错:

Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' blob: filesystem:".

再看看Firefox code review拒绝说明:

Extensions defining a content security policy that allows eval ('unsafe-eval') are generally not allowed for security and performance reasons. eval is only necessary in rare cases. Please use a different method.

所以,我们是无法在Firefox Extension(Add-ons)里使用eval类方法的。

为什么要使用eval类方法

最明显的原因,如:模板解析。我们知道,没有模板解析在渲染数据时会非常的麻烦和不好看,而大多数的模板解析都会使用eval来将字符串转为js function,以便调用。这其实是JS非常有优势的地方,几个简单的正则就可以有一整套模板解析机制。可惜无法简单的使用它们来帮助开发。

解决方法

使用沙盒模式

在Chrome的文档:Using eval in Chrome Extensions. Safely有讲解,如果使用沙盒模式来安全的使用eval的模板解析库,可以直接参考:https://developer.chrome.com/extensions/sandboxingEval

因为Firefox和Edge都是使用Chrome同种的Extension,所以肯定是通用的。

它的问题:

因为它实际是使用iframe模式,所以当你的模块拆分比较细的时候,并不好处理,而且不是所有Extension都好使用它,所以它肯定不是一个好的选择。

预编译模式

这其实也是Chrome推荐的一种方法,使用的时候先编译好,调用的是编译后的,这样就可以完全的避免使用eval类方法。但这里仍然有些问题,最主要是如何兼容开发/发布模式。这里可以有两种方法:

  1. watch监听文件修改,执行编译。很多库也有使用此方法
  2. 开发保持使用eval不变,发布编译时将其移除,同时编译模板,并更换调用的代码

我不是太喜欢watch监听的方式,因为不管怎么样,都有可能慢一拍,体验不好,所以选择第2种,也是YuiAPI使用的方法,简单说明。

开发的时候,保持使用eval不变

mainfest.json:

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

解析:

evalViewFunc: function(model, name) {
    let key = model + "." + name;
    if (!this.hasOwnProperty(key)) {
        let content = this[model][name](),
            _html = [];
        let txt = ["App.view.extend('"+ model +"."+name+"', function() {"];
        txt.push("this.init = function(data) {");
        txt.push("var html = '';");
        content = content.split('\n');
        for (let i in content) {
            _html.push(this.parse(content[i]));
        }
        txt.push(_html.join(""));
        txt.push("return html;");
        txt.push("}");
        txt.push("});");
        eval(txt.join(""));
    }
}

编译的时候

  1. 读取mainfest.json将content_security_policy去掉后,再生成新的mainfest.json文件
  2. 根据模板信息,编译生成一个view.js,将引用模板的调用去掉,最后引用view.js

这样发布后view.js会直接运行,而在开发中使用view的方法都没有问题。

可以参考:https://github.com/yuiitsu/YuiAPI

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.