渲染由外部代码添加的Vue组件标记

时间:2018-06-08 15:21:22

标签: javascript vue.js

我正在尝试将简单的Vue组件添加到旧版应用中。目标是能够使用一些较新的技术而无需重写所有内容。

基本上我希望能够将<tags-input>元素放在我想要的任何地方,并让Vue将其替换为组件。

我已经实例化了Vue并在html中添加了一些<tags-input>个元素。我将它们用作ASP WebForms最初生成的表行的一部分。

import Vue from 'vue'
import TagsInput from './ClientTags'
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
import '../style.css';
Vue.config.productionTip = false

window.VueApp = new Vue({
  el: '#app',
  components: {
    TagsInput
  }
})

最初,<tags-input>元素可以很好地呈现。问题是外部遗留JS代码向表中添加了新行(WebForms执行一些 auto-magic 分页)。将新行添加到DOM后,Vue不会在其中呈现<tags-input>个元素。

所以,我的目标是:

每当将一个新的<tags-input>元素添加到DOM(通过外部JS)时,它应该由Vue呈现并添加到window.VueApp。

1 个答案:

答案 0 :(得分:0)

我终于明白了(感谢Sphinx评论)。在我的情况下,我可能根本不应该使用Vue应用程序。相反,我应该手动创建和安装我的组件,如下所示:

<html>

<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

<script>
var MyComponent = Vue.component('my-component', {
  // camelCase in JavaScript
  props: ['someTitle'],
  template: '<b>[XYZ {{ someTitle }}]</b>  '
})

function dashToCamelCase( myStr ) {
	return myStr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
}

function getAttributes ( node ) {
	var i,
		attributeNodes = node.attributes,
		length = attributeNodes.length,
		attrs = {};

	for ( i = 0; i < length; i++ ) attrs[dashToCamelCase(attributeNodes[i].name)] = attributeNodes[i].value;
	return attrs;
}

function renderExisting(componentElementName, componentCreator){
	$(componentElementName).each(function(){
		var props = getAttributes(this)
		var component = componentCreator(props)
		component.$mount(this)
	})
}

function renderNew(appElementId, componentElementName, componentCreator){
	var obs = new MutationObserver(function(mutations, observer) {
	  $.each(mutations, function (i, mutation) {
		var addedNodes = $(mutation.addedNodes);
		var selector = componentElementName
		var filteredEls = addedNodes.find(selector).addBack(selector);
		filteredEls.each(function(){
			var props = getAttributes(this)
			var component = componentCreator(props)
			component.$mount(this)
		});
	  });
	});

	var canvasElement = $(appElementId)[0];
	obs.observe(canvasElement, {childList: true, subtree: true});
}

function setUpRendering(appElementId, componentElementName, componentCreator){
	renderExisting(componentElementName, componentCreator)
	renderNew(appElementId, componentElementName, componentCreator)
}

$(function(){
	setUpRendering('#myApp', 'my-component', (props) => new MyComponent({propsData: props}))
});
</script>

<script>
function addMyTag(){
	$('#myApp').append( '<my-component some-title="' + (new Date()).getTime() + '"></my-component>' )
}
</script>

</head>

<body>

<button onclick='addMyTag()'>Add!</button>

<div id="myApp">
<my-component some-title="aaa"></my-component>
<my-component some-title="bbb"></my-component>
<my-component some-title="ccc"></my-component>
<div>

</body>

</html>

我很乐意接受更好的答案。