You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

AngularJS ui-router嵌套路由异常:指定ui-sref触发双模板加载求解决

解决AngularJS ui-router嵌套状态模板同时加载的问题

看起来你遇到的问题是因为两个同级子状态的URL模式冲突,或者没有明确指定模板要插入的目标ui-view,导致触发其中一个状态时,另一个状态的模板也被意外加载了。下面是具体的解决步骤:

问题分析

你的practice.exam.service.competitiveSamplePaperpractice.exam.service.subject都是practice.exam.service的同级子状态,但它们的URL都使用了无区分度的动态参数({samplePaperNumber}{subjectName}),ui-router无法通过URL模式精准区分这两个状态;另外,如果没有明确指定views配置,子状态的模板可能会被错误地插入到父状态的ui-view中,甚至因为状态匹配逻辑导致两个状态同时被激活。

解决方案

方案1:给子状态添加唯一的URL前缀

给两个子状态的URL添加不同的静态前缀,让它们的URL模式明确区分,这样ui-router就能精准匹配到目标状态:

$stateProvider
  .state('main', { url:'/', templateUrl:'views/main.html', controller:'MainCtrl' })
  .state('practice', { url:'/practice', templateUrl:'views/practice/practice.html', controller:'PracticeCtrl' })
  .state('practice.exam', { url:'/{examName}', templateUrl:'views/practice/exam.html', controller:'ExamCtrl' })
  .state('practice.exam.service', { url:'/{serviceName}', templateUrl:'views/practice/service.html', controller:'ServiceCtrl' })
  // 给competitiveSamplePaper添加/sample前缀
  .state('practice.exam.service.competitiveSamplePaper', { 
    url:'/sample/{samplePaperNumber}', 
    templateUrl:'views/practice/competitive_sample_paper.html', 
    controller:'CompetitiveSamplePaperCtrl' 
  })
  // 给subject添加/subject前缀
  .state('practice.exam.service.subject', { 
    url:'/subject/{subjectName}', 
    templateUrl:'views/practice/subject.html', 
    controller:'SubjectCtrl' 
  })

这样,跳转practice.exam.service.subject({subjectName: 'Physics'})时,URL会是/practice/{examName}/{serviceName}/subject/Physics,不会和competitiveSamplePaper的URL模式混淆,也就只会加载对应的subject模板。

方案2:明确指定子状态的目标ui-view

如果不想修改URL结构,可以通过views配置明确指定每个子状态的模板要插入到父状态的哪个ui-view中,确保每次只有一个子模板被加载:

首先,在practice.exam.service的模板(views/practice/service.html)中,给ui-view指定一个名称:

<!-- views/practice/service.html -->
<div ui-view="content"></div>

然后修改状态定义,给每个子状态添加views配置:

$stateProvider
  .state('main', { url:'/', templateUrl:'views/main.html', controller:'MainCtrl' })
  .state('practice', { url:'/practice', templateUrl:'views/practice/practice.html', controller:'PracticeCtrl' })
  .state('practice.exam', { url:'/{examName}', templateUrl:'views/practice/exam.html', controller:'ExamCtrl' })
  .state('practice.exam.service', { url:'/{serviceName}', templateUrl:'views/practice/service.html', controller:'ServiceCtrl' })
  .state('practice.exam.service.competitiveSamplePaper', { 
    url:'/{samplePaperNumber}', 
    views: {
      // 指定插入到practice.exam.service状态下的content ui-view
      'content@practice.exam.service': {
        templateUrl:'views/practice/competitive_sample_paper.html',
        controller:'CompetitiveSamplePaperCtrl'
      }
    }
  })
  .state('practice.exam.service.subject', { 
    url:'/{subjectName}', 
    views: {
      'content@practice.exam.service': {
        templateUrl:'views/practice/subject.html',
        controller:'SubjectCtrl'
      }
    }
  })

这种方式下,两个子状态的模板都会替换同一个命名ui-view,触发跳转时只会加载对应状态的模板,不会同时加载两个。

方案3:检查状态激活逻辑

最后,确认你的代码中没有同时触发两个状态的跳转操作,比如是否有额外的$state.go调用,或者ui-sref是否误写了多个状态名称。

内容的提问来源于stack exchange,提问作者Nitish Kumar

火山引擎 最新活动