gpt4 book ai didi

javascript - 如何在单击时调用自定义元素成员方法?

转载 作者:行者123 更新时间:2023-12-03 11:11:41 25 4
gpt4 key购买 nike

又名如何在访问自定义元素方法时绕过或避免不允许在 Angular 表达式中引用 DOM 节点

所以我正在使用 David Shapiro 的小型库 angular-custom-element尝试自定义元素等功能,以保证我们的组件面向 future 。我已经走了很远了,他们似乎已经注册了。但是,在示例中,它尝试在指令示例中的 ng-click 内调用元素的成员函数。

 template: '<div ng-click="el.elementMethod()">{{ el.propertyNameOne }} CUSTEM ELEMENT CLICK ME</div>',

下面是完整的代码和可运行的片段。在您单击“自定义元素”之前,它不会引发错误

我尝试在方法中添加“return true”来绕过其他帖子建议的安全性,但无济于事。是否有替代实现?

angular.module('appy', []);

angular.module('appy.elementDirectives', ['customElements']);

var app = angular.module('appy', [
'appy',
'appy.elementDirectives'
]);



app.config( function($customElementsProvider ) {
'use strict';
var definitions = [
{
name: 'shiny-button',
definition: {
parent: HTMLButtonElement,
properties: {

propertyNameOne: {
get: function () {
// do any value calculations
var valueVar = 'testFooValue';
return valueVar;
},
set: function (val) {
// do any value calculations
val = val + 'X';
return val;
},
attribute: {
name: 'property-one'
}
},
propertyNameTwo: {

attribute: {},
value: 'hello',
readOnly: true
},
booleanProperty: {
attribute: {
name: 'bool-prop',
// note that "true" here just signifies that the attr should
// treated as a boolean,
boolean: true // default is false
},
value: true // default is false
}
},

// In all callbacks "this" referes to the element instance
callbacks: {
created: function () {
console.log('created')

},

// is called when the element is inserted into the DOM
attached: function () {
console.log('attached')
},

// is called when the element is removed from the DOM
detached: function () {
// include any cleanup logic
console.log('detached')
},

// called upon any attribute change including attr set programatically
// during element instantiation (but not if the elem already exists in markup)
attributeChanged: function (attr, oldVal, newVal) {
console.log('attributeChanged', attr, oldVal, newVal)
}
},
members: {

elementMethod: function (args) {
alert("member click");
console.log('clicked member');
return true;
},


memberNameOne: {
get: function (val) {
return val;
},
set: function (val) {
val = val + 'X';
return val;
},
value: 'blah blah',
readOnly: true
}
}
}
}];

console.log("Register Element");
//$customElementsProvider.register( 'shiny-button', definitions[0].definition );
$customElementsProvider.registerCollection(definitions);
});



app.controller('MainCtrl', function($scope) {
var that = this;

$scope.showTest = true;

$scope.testButtonClick = function(){
alert("testButton click")
}

});

app.directive('shinyButton', function($customElements) {
return {
restrict:'E',
scope: {
nothingHereYet: '=propertyNameOne'
},
replace: false,
template: '<div ng-click="el.elementMethod()">{{ el.propertyNameOne }} CUSTEM ELEMENT CLICK ME</div>',

controllerAs:'shinyCtrl',

// 3.4 at a minimum inject $scope and $element into your controller
controller: function($scope, $element, $attrs, $document, $log){

// 4. This is the only line of code that is required.
// this command takes care of binding all custom properties
// to the $scope including triggering a $digest() when
// any custom property is changed outside of Angular
// After this line you can enjoy the full power of AngularJS
// when interacting with your Custom Element
$customElements.$watchElement($scope, $element);

$document.on('member:changed', function(evt){
if(evt.detail.propName == 'a protopype prop we need to watch'){
// i.e. $scope.el.__proto__.memberNameOne
$scope.$digest();
}
});

// 4.2
// bind to an event on the element
// since all prop changes generate a change event
// other frameworks in the page can import and react
// to the same component
$element.on('prop:changed', function(evt){
$log.log(evt.detail);
$scope.$emit(evt.detail);
});




// 4.3
// gets the original custom elem config obj mostly for any debug
var info = $customElements.info($element);

//$customElements.$importElement($scope, $element, ['array','of','property','names']);

},
link: function(scope, iElement, iAttrs, controller){
// ...
}

};
});





/*! (C) WebReflection Mit Style License */

/*
* AngularCustomElement
* https://github.com/dgs700/angular-custom-element

* Version: 0.2.0 - 2014-11-01
* License: MIT
*/



/* Requires a Custom Element polyfill for all browsers other than Chrome
Recommended: https://github.com/WebReflection/document-register-element */
/*! (C) WebReflection Mit Style License */
(function(e,t,n,r){"use strict";function q(e,t){for(var n=0,r=e.length;n<r;n++)J(e[n],t)}function R(e){for(var t=0,n=e.length,r;t<n;t++)r=e[t],$(r,c[z(r)])}function U(e){return function(t){g.call(L,t)&&(J(t,e),q(t.querySelectorAll(h),e))}}function z(e){var t=e.getAttribute("is");return d.call(l,t?t.toUpperCase():e.nodeName)}function W(e){var t=e.currentTarget,n=e.attrChange,r=e.prevValue,i=e.newValue;t.attributeChangedCallback&&e.attrName!=="style"&&t.attributeChangedCallback(e.attrName,n===e.ADDITION?null:r,n===e.REMOVAL?null:i)}function X(e){var t=U(e);return function(e){t(e.target)}}function V(e,t){var n=this;O.call(n,e,t),B.call(n,{target:n})}function $(e,t){N(e,t),I?I.observe(e,_):(H&&(e.setAttribute=V,e[i]=F(e),e.addEventListener(u,B)),e.addEventListener(o,W)),e.createdCallback&&(e.created=!0,e.createdCallback(),e.created=!1)}function J(e,t){var n,r=z(e),i="attached",s="detached";-1<r&&(C(e,c[r]),r=0,t===i&&!e[i]?(e[s]=!1,e[i]=!0,r=1):t===s&&!e[s]&&(e[i]=!1,e[s]=!0,r=1),r&&(n=e[t+"Callback"])&&n.call(e))}if(r in t)return;var i="__"+r+(Math.random()*1e5>>0),s="extends",o="DOMAttrModified",u="DOMSubtreeModified",a=/^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)+$/,f=["ANNOTATION-XML","COLOR-PROFILE","FONT-FACE","FONT-FACE-SRC","FONT-FACE-URI","FONT-FACE-FORMAT","FONT-FACE-NAME","MISSING-GLYPH"],l=[],c=[],h="",p=t.documentElement,d=l.indexOf||function(e){for(var t=this.length;t--&&this[t]!==e;);return t},v=n.prototype,m=v.hasOwnProperty,g=v.isPrototypeOf,y=n.defineProperty,b=n.getOwnPropertyDescriptor,w=n.getOwnPropertyNames,E=n.getPrototypeOf,S=n.setPrototypeOf,x=!!n.__proto__,T=n.create||function K(e){return e?(K.prototype=e,new K):this},N=S||(x?function(e,t){return e.__proto__=t,e}:w&&b?function(){function e(e,t){for(var n,r=w(t),i=0,s=r.length;i<s;i++)n=r[i],m.call(e,n)||y(e,n,b(t,n))}return function(t,n){do e(t,n);while(n=E(n));return t}}():function(e,t){for(var n in t)e[n]=t[n];return e}),C=S||x?function(e,t){g.call(t,e)||$(e,t)}:function(e,t){e[i]||(e[i]=n(!0),$(e,t))},k=e.MutationObserver||e.WebKitMutationObserver,L=(e.HTMLElement||e.Element||e.Node).prototype,A=L.cloneNode,O=L.setAttribute,M=t.createElement,_=k&&{attributes:!0,characterData:!0,attributeOldValue:!0},D=k||function(e){H=!1,p.removeEventListener(o,D)},P=!1,H=!0,B,j,F,I;k||(p.addEventListener(o,D),p.setAttribute(i,1),p.removeAttribute(i),H&&(B=function(e){var t=this,n,r,s;if(t===e.target){n=t[i],t[i]=r=F(t);for(s in r){if(!(s in n))return j(0,t,s,n[s],r[s],"ADDITION");if(r[s]!==n[s])return j(1,t,s,n[s],r[s],"MODIFICATION")}for(s in n)if(!(s in r))return j(2,t,s,n[s],r[s],"REMOVAL")}},j=function(e,t,n,r,i,s){var o={attrChange:e,currentTarget:t,attrName:n,prevValue:r,newValue:i};o[s]=e,W(o)},F=function(e){for(var t,n,r={},i=e.attributes,s=0,o=i.length;s<o;s++)t=i[s],n=t.name,n!=="setAttribute"&&(r[n]=t.value);return r})),t[r]=function(n,r){y=n.toUpperCase(),P||(P=!0,k?(I=function(e,t){function n(e,t){for(var n=0,r=e.length;n<r;t(e[n++]));}return new k(function(r){for(var i,s,o=0,u=r.length;o<u;o++)i=r[o],i.type==="childList"?(n(i.addedNodes,e),n(i.removedNodes,t)):(s=i.target,s.attributeChangedCallback&&i.attributeName!=="style"&&s.attributeChangedCallback(i.attributeName,i.oldValue,s.getAttribute(i.attributeName)))})}(U("attached"),U("detached")),I.observe(t,{childList:!0,subtree:!0})):(t.addEventListener("DOMNodeInserted",X("attached")),t.addEventListener("DOMNodeRemoved",X("detached"))),t.addEventListener("readystatechange",function(e){q(t.querySelectorAll(h),"attached")}),t.createElement=function(e,n){var r,i=M.apply(t,arguments);return n&&i.setAttribute("is",e=n.toLowerCase()),r=d.call(l,e.toUpperCase()),-1<r&&$(i,c[r]),i},L.cloneNode=function(e){var t=A.call(this,!!e),n=z(t);return-1<n&&$(t,c[n]),e&&R(t.querySelectorAll(h)),t});if(-1<d.call(l,y))throw new Error("A "+n+" type is already registered");if(!a.test(y)||-1<d.call(f,y))throw new Error("The type "+n+" is invalid");var i=function(){return t.createElement(p,u&&y)},o=r||v,u=m.call(o,s),p=u?r[s]:y,g=l.push(y)-1,y;return h=h.concat(h.length?",":"",u?p+'[is="'+n.toLowerCase()+'"]':p),i.prototype=c[g]=m.call(o,"prototype")?o.prototype:T(L),q(t.querySelectorAll(h),"attached"),i}})(window,document,Object,"registerElement");
/*
* AngularCustomElement
* https://github.com/dgs700/angular-custom-element

* Version: 0.2.0 - 2014-11-01
* License: MIT
*/
!function(){"use strict";function a(){function a(a,b){function c(a){var b=parseFloat(a);return!isNaN(b)&&isFinite(b)?b:a}function e(a,b,c,d,e,f){if(!c)return b;c.setterCalled[e]=!0;try{e&&f?b?c.setAttribute(e,""):c.removeAttribute(e):e&&c.setAttribute(e,b),c.onPropChange(b)}catch(g){}return d=f?!!c[a]:c[a],c.propChangeNotify(c,a,b,d,e,"prop:changed"),b}if("string"!=typeof a||!/.*-.*/.test(a))return console.error("Invalid element name: ",a),this;if(a=a.toLowerCase(),d[a])return this;var f=b.parent?b.parent.prototype:b["extends"]?Object.create(document.createElement(b["extends"]).constructor).prototype:HTMLElement.prototype,g=b["extends"]||null,h=b.properties||{},i=b.members||{},j={prototype:{}},k=function(){};for(var l in i)!function(a,b){function c(a,b,c){return document.dispatchEvent(new CustomEvent("member:changed",{detail:{propName:c,newValue:a,oldValue:b||null}})),a}var d,e,f,g,h,i,l=this;"function"==typeof b[a]?j.prototype[a]={enumerable:!0,value:b[a]}:(d=b[a],i=d.readOnly||!1,g=d.value||null,e="function"==typeof d.get?function(){return g=d.get.call(l,g)}:function(){return g},f=i?k:"function"==typeof d.set?function(b){b=d.set.call(l,b),h=this[a]||null,g=c(b,h,a)}:function(b){h=this[a]||null,g=c(b,h,a)},j.prototype[a]={get:e,set:f,enumerable:!0})}(l,i);j.prototype.registerCallback={value:function(a,b){a.onPropChange=b},enumerable:!0},j.prototype.propChangeNotify={value:function(a,b,c,d,e,f){a.dispatchEvent(new CustomEvent(f,{detail:{propName:b,newValue:c,oldValue:d,attrName:e||null}}))},enumerable:!0},j.prototype.definition={value:b};var m,n=b.callbacks||{},o=n.created||k,p=n.attached||k,q=n.detached||k,r=n.attributeChanged||k,s={},t=[];for(m in h)!function(a,b){t.push(function(d){var f,g,h,i,l,m,n,o,p;o=!1,l=null,g=null,f=b[a],n=f.readOnly||!1,p=f.attribute?!0:!1,o=p&&f.attribute.boolean?!0:!1,p&&!n&&d?(g=f.attribute.name?f.attribute.name:a.toLowerCase(),s[g]={name:a,bool:o},o?l=d.hasAttribute(g)?!0:f.value?!0:!1:(l=d.hasAttribute(g)?d.getAttribute(g):f.value?f.value:null,l=c(l)),d.hasAttribute(g)||(o&&l?d.setAttribute(g,""):o?d.removeAttribute(g):d.setAttribute(g,l)),d.setterCalled[g]=!1):o&&!d?l=f.value?!0:!1:(l=f.value?f.value:null,l=c(l)),h="function"==typeof f.get?f.get:function(){return l},i=n?k:"function"==typeof f.set?function(b){b=f.set.call(d,b),b=e(a,b,d,m,g,o),l=b}:function(b){l=e(a,b,d,m,g,o)},d?Object.defineProperty(d,a,{get:h,set:i,enumerable:!0,configurable:!0}):j.prototype[a]={get:h,set:i,enumerable:!0}})}(m,h),t.forEach(function(a){a.call(this,null)});j.prototype.createdCallback={enumerable:!0,value:function(){this.setterCalled={};var a=this;t.forEach(function(b){b.call(a,a)});var b=o?o.apply(this,arguments):null;return b}},j.prototype.attributeChangedCallback={enumerable:!0,value:function(a,b,d){if(s[a]&&!this.setterCalled[a]){var e=s[a];e.bool&&""===d&&(d=!0),this.setterCalled[a]=!1,this[e.name]=e.bool?!!d:c(d)}var f=r?r.apply(this,arguments):null;return f}},j.prototype.attachedCallback={enumerable:!0,value:function(){this.classList.remove("unresolved");var a=p?p.apply(this,arguments):null;return a}},j.prototype.detachedCallback={enumerable:!0,value:function(){var a=q?q.apply(this,arguments):null;return a}};var u={prototype:Object.create(f,j.prototype)};return g&&(u["extends"]=g),d[a]=document.registerElement(a,u),this}function b(a){return Array.isArray(a)?(a.forEach(function(a){var b=a.name,c=a.definition;return"string"!=typeof b||c!==Object(c)?(console.warn("bad element definition format"),!1):void e.register(b,c)}),!0):(console.error("parameter to registerCollection must be an array"),!1)}function c(){return{info:function(a){return a[0].__proto__.definition},$watchElement:function(a,b,c){c=c||!1,a.el=b[0],c||a.el.registerCallback(a.el,function(){return setTimeout(function(){a.$digest()},0),!0})},$importElement:function(a,b,c,d){var e=null,f=null;return Array.isArray(c)&&(c.forEach(function(a,b,c){c[b]=c[b].toLowerCase()}),e=new MutationObserver(function(b){b.forEach(function(b){-1!==c.indexOf(b.attributeName)&&a.$digest()})}).observe(b[0],{attributes:!0,childList:!0,characterData:!0,attributeOldValue:!0})),d&&(f=b.addEventListener(d,function(){a.$digest()})),Array.isArray(c)&&d?{observer:e,eventBinding:f}:!1}}}var d={};window.registeredElements=this.registeredElements=d,this.register=a;var e=this;this.registerCollection=b,this.$get=c,c.$inject=["$window"]}angular.module("customElements",["ng"]).provider("$customElements",a)}(window);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="appy">

<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link data-require="bootstrap-css@*" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.2.x" src="https://code.angularjs.org/1.2.6/angular.js" data-semver="1.2.25"></script>
<script src="angular-custom-element.js"></script>

</head>
<body ng-controller="MainCtrl as vm">

<shiny-button>this will be replaced by directive template</shiny-button>

<br/><br/>

<div ng-show="showTest" ng-click="testButtonClick()">Test Click Div</div>


</html>

最佳答案

这是因为 AngularJS 1.x 尚不支持 Web 组件友好。它假设如果您直接从 Angular 宇宙中引用 DOM 属性,那么您一定是愚蠢的,因为该代码可能是恶意的,或者它只是违反了 Angular 代码应该完全封装于外部世界并且框架处理所有外部的原始概念。相互作用。虽然在大多数情况下确实如此,但它是在我们知道自定义元素很快将成为我们构建可重用 UI Web 组件的方式的核心之前出现的。

在 NG 2.0 之前,您可能需要执行以下操作:

替换这个:

<div ng-click="el.elementMethod()">

这样:

<div ng-click="callMember()">

$scope.callMember = function(){
$scope.el.elementMethod();
};

使用替换代码没有错误。

有趣的是,通过 {{ el.propertyNameOne }} 进行相同的 DOM 访问不会导致 Angular 抛出相同的错误。想想吧。

关于javascript - 如何在单击时调用自定义元素成员方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27554992/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com