将UI路由器状态parsing为无Angular的URL

我有一个Angular 1.5.9 Web应用程序和一个Node.js / Sails.js 0.12后端。 在Angular里面运行UI路由器0.4来处理状态。

状态定义可能看起来像这样(相当香草,我会说):

$stateProvider.state('dogs', { url: '/ourdogsarecute_{specialIDofDog} }). state('dogs.specialDogState', { url: '/specialinfo_{specialInfoOfDog}' }); 

现在,出现以下情况: 在后端(即在Angular之外) ,我必须转换一个Angular UI路由器状态链接,例如{stateName: 'dogs.specialDogState', stateParams: {specialIDofDog: 11212, specialInfoOfDog: 'likesbones' } }转换为有效的url,例如https://www.our-app.dog/ourdogsarecute_11212/specialinfo_likesbones

我不知道如何做到这一点,没有大量的手动工作。 是否有一种用于UI路由器状态的parsing器作为节点模块?

我可以以某种方式访问​​后端状态定义所在的前端代码。 这不是问题。 问题是从状态链接到URL的转换。

UI-Router 1.0将代码拆分成ui-router核心和ui-router的angularjs。 您可以在您的节点后端使用ui-router核心(没有外部依赖关系)来生成这些url。 由于您的状态已经作为JSON文件提供,您只需在后端注册具有ui-router core的状态,然后使用状态对象生成URL即可。

在你的节点后端添加ui-router核心

npm install --save @uirouter/core

 // The library exports most of its code var UIR = require('@uirouter/core'); // Create the router instance var router = new UIR.UIRouter(); // Get the state registry var registry = router.stateRegistry; var states = [ { name: 'dogs', url: '/ourdogsarecute_{specialIDofDog}' }, { name: 'dogs.specialDogState', url: '/specialinfo_{specialInfoOfDog}' }, ]; states.forEach(state => registry.register(state)); var params = { specialIDofDog: '11212', specialInfoOfDog: 'lovesbones' }; // Get the internal state object var stateObj = registry.get('dogs.specialDogState').$$state(); // Generate the URL console.log(stateObj.url.format(params)); 

作为参考:我的解决scheme现在看起来像这样。 首先,我把状态定义放到一个单独的文件中,使得从外部访问它变得更容易:

 var myStates = [ { name: 'dogs', stateProperties: { url: '/ourdogsarecute_{specialIDofDog}' } }, { name: 'dogs.specialDogState', stateProperties: { url: '/specialinfo_{specialInfoOfDog}' } }]; 

然后在我的app.config

 for(var i = 0; i < myStates.length; i++) { $stateProvider.state(myStates[i].name, myStates[i].stateProperties); } 

在后端,我创build了这个函数:

 /** * @description Turns state name and state params into a URL string, using stateLinks definition synchronized from front end (being UI router state definitions) * @param {string} stateName Something like 'dogs.info.specialAttributes' * @param {object} stateParams Something like {dogID: 34346346, dogStatus: 'private', dogInfo: 'food'} * @returns {string} URL */ stateLinkResolve: function(stateName, stateParams) { if(!(stateName && stateName.length > 0)) { return '/'; } var resultUrl = ''; var splittedSubStates = stateName.split('.');// split "dogs.info.specialAttributes" into ["dogs","info","specialAttributes"] var currentStateInHierarchy = ''; for(var i = 0; i < splittedSubStates.length; i++) { /* Add dot if "in between": not the first, not the last. So that "dogs" remains "dogs", but when going to "dogs.info", we want the dot in between */ if(i > 0 && i < (splittedSubStates.length + 1) ) { currentStateInHierarchy += '.'; } currentStateInHierarchy += splittedSubStates[i]; // Add current splitted name (being only the last name part) to the state name in its context. Ie when doing "info", we want to access "dogs.info" var currState = _.find(stateDefs,{name: currentStateInHierarchy}); var urlRaw = currState.stateProperties.url; /* uiRouter URLs may contain wildcards for parameter values like /ourdogs_{dogID:int}_{dogStatus}/:dogInfo. We go through each of these three types and replace them with their actual content. */ for(var currentParam in stateParams) { urlRaw = urlRaw.replace(':' + currentParam, stateParams[currentParam]); // search for ":paramName" in URL urlRaw = urlRaw.replace('{' + currentParam + '}', stateParams[currentParam]); // search for "{paramName}" in URL // search for "{paramName:paramType}" in URL var uiRouterParamTypes = ["hash", "string", "query", "path", "int", "bool", "date", "json", "any"]; for(var j = 0; j < uiRouterParamTypes.length; j++) { urlRaw = urlRaw.replace('{' + currentParam + ':' + uiRouterParamTypes[j] + '}', stateParams[currentParam]); } } resultUrl += urlRaw; } return resultUrl; } 

问题是:对于边缘情况,这可能会失败,并且对于UI状态路由器实现的新function以及URL的构build方式,肯定会失败。 所以,仍然希望能够直接使用UI路由器魔法的解决scheme。