在做用户免登功能的时候遇到了一个困扰挺久的问题,在钉钉提供的示例代码中,已经为我们写出了获取到userid的方法,并且将值设置到了data里面

data:{//设置值  在login.axml上
        corpId: '',
        authCode:'',
        userId:'',
        userName:'',
        hideList: false,//列表隐藏
    }




 dd.getAuthCode({//获得用户免登码
            success:(res)=>{//如果成功获取,给个res(Result结果)对象,并且执行dd.httpRequest({})请求方法
                this.setData({//设置上面有定义的具体data数据
                    authCode:res.authCode//将authCode值设置为获取到的值
                })
                //dd.alert({content: "step1"});
                dd.httpRequest({//执行dd.httpRequest方法
                    url: url,//设置请求地址
                    method: 'POST',//请求方式
                    data: {//传递的数据
                        authCode: res.authCode//获取到的authCode值,设置给authCode变量
                    },
                    dataType: 'json',//数据类型JSON
                    success: (res) => {//如果dd.httpRequest()方法请求成功,即获取到了userid和username
                        // dd.alert({content: "step2"});
                        console.log('success----',res)//控制台打印出来
                        let userId = res.data.result.userId;//路径在控制台里有体现
                        let userName = res.data.result.userName;
                        this.setData({//设置上面有定义的具体data数据
                            userId:userId,
                            userName:userName,
                            hideList:false
                        })
                    },
                    fail: (res) => {//如果dd.httpRequest()方法请求失败
                        console.log("httpRequestFail---",res)//控制台打印信息
                       dd.alert({content: JSON.stringify(res)});//login.axml页面弹出错误信息
                    },
                    complete: (res) => {//调用结束的回调函数,(请求成功、失败都会执行)
                        dd.hideLoading();
                    }

                });
            },
            fail: (err)=>{//如果获取用户免登码失败
                // dd.alert({content: "step3"});
                dd.alert({//弹出错误信息
                    content: JSON.stringify(err)
                })
            }
        })

而我要做的事就是拿到这个userid值,并且传递给我要链接到的地址作为参数。

这里我有两个页面,First和login页面  都在page的子目录下,两个文件夹同级。

First页面是用来放外部页面的。而login页面是一开始加载显示的页面,获取userid的函数执行也在这个页面的js里。

钉钉开发文档提供了一个组件web-view 可以用来连接到外部地址。但是里面的参数src不能直接用+的方式直接拼接,经过摸索,可以使用{{}}传值的方式:

①先在First.axml页面将要访问的地址设置成这种方式

<web-view src={{a}}{{b}}{{c}} />

②在对应的First.js页面Page里配置:

Page({
   data: {//data里的数据只能传递给axml页面中有用{{}}来设置值的
    a:'https://www.',
    b:'baidu',
    c:'.com',
  

这种方式就可以实现参数的拼接。a、b、c里面的数据可以自己按照自己的需求来写。

这里有个很重要的不能忽视的点!!因为钉钉E应用只允许应用内的页面跳转,我们刚才说的跳转到外部页面实际上也是跳转到钉钉E应用的另一个页面罢了,只是说它将外部页面自动铺满E应用的页面。即在login.axml页面使用dd.navigateTo方法

 dd.navigateTo({//跳转到另一个页面
       url:'../First/First'
          })

而这个页面的地址链接到的就是上面我们在另一个页面用web-view 方法设置的地址。

我如何取出login.js 中data 里面的userid并将它作为参数传递给First页面?

方法不难,在要跳转的路径上使用?来增加参数:

 dd.navigateTo({//跳转到另一个页面
       url:'../First/First?userId='+this.data.userId
          })

这样子,当我们触发这个跳转事件时,就会将userId的值一起传递到要接收的页面。

那First页面如何接收传递过来的值?

我们在First.js页面的onLoad方法中接收:

 onLoad(query) {
   this.setData({
     userId:query.userId
   })

  }

这样子,在First页面加载的时候,就会将login页面传递过来的userid值设置到data中。

 

这里有个很细节的地方!!!!

我们在从login页面跳转到First页面(外部页面)时,我们刚才是用的

 dd.navigateTo({//跳转到另一个页面
       url:'../First/First?userId='+this.data.userId
          })

这种方法。用这个方法我们要保证的首先是:this.data.userId是已经有值的。否则你传递的只是一个空值。所以我们应该在login这个页面刚开始加载的时候就要实现获取到userid这个方法了。即在onLoad()方法里去实现:

onLoad(){//页面加载时执行的方法
        dd.showLoading();//显示加载效果
        dd.getAuthCode({//获得用户免登码
            success:(res)=>{//如果成功获取,给个res(Result结果)对象,并且执行dd.httpRequest({})请求方法
                this.setData({//设置上面有定义的具体data数据
                    authCode:res.authCode//将authCode值设置为获取到的值
                })
                //dd.alert({content: "step1"});
                dd.httpRequest({//执行dd.httpRequest方法
                    url: url,//设置请求地址
                    method: 'POST',//请求方式
                    data: {//传递的数据
                        authCode: res.authCode//获取到的authCode值,设置给authCode变量
                    },
                    dataType: 'json',//数据类型JSON
                    success: (res) => {//如果dd.httpRequest()方法请求成功,即获取到了userid和username
                        // dd.alert({content: "step2"});
                        console.log('success----',res)//控制台打印出来
                        let userId = res.data.result.userId;//路径在控制台里有体现
                        let userName = res.data.result.userName;
                        this.setData({//设置上面有定义的具体data数据
                            userId:userId,
                            userName:userName,
                            hideList:false
                        })
                    },
                    fail: (res) => {//如果dd.httpRequest()方法请求失败
                        console.log("httpRequestFail---",res)//控制台打印信息
                       dd.alert({content: JSON.stringify(res)});//login.axml页面弹出错误信息
                    },
                    complete: (res) => {//调用结束的回调函数,(请求成功、失败都会执行)
                        dd.hideLoading();
                    }

                });
            },
            fail: (err)=>{//如果获取用户免登码失败
                // dd.alert({content: "step3"});
                dd.alert({//弹出错误信息
                    content: JSON.stringify(err)
                })
            }
        })

        let _this = this;//定义_this变量,设置为当前页面

        this.setData({//设置上面有定义的具体data数据
            corpId: app.globalData.corpId
        })


        //dd.alert({content: "step1"});
         }

总结:

这样实现后,我们的效果就是在第一个页面加载完成的时候,我们已经实现了获取userid的方法,并且将值设置到了data当中。当我们触发跳转事件(比如设置一个按钮,触发点击事件实现跳转)时,能够将data中的值作为参数一同传递给另一个页面,同时另一个页面接收成功后,把这个值设置到自己页面的data中。如此访问外部地址传参的问题就成功解决了!

 

在这个过程中我遇到了一个很细节很细节的问题:我可不可以在访问外部地址的这个页面(First)的js里自己获取userid然后设置到自己的data里面?这样是不是更简单?

告诉你这是不行的!!!因为我就是踩这坑的!

原因是什么?

我如果在First这个页面的js函数里获取userid,这个是可以获取得到的,并且也可以设置到data里。要实现免登肯定是要在点击跳转时就要获取到userid并传给地址作为参数。 所以你至少必须要把获取的方法写在onload方法里面。理想状况下,你会这样认为:当点击跳转时,页面加载的时候实现了获取userid的方法获取到了id,并已经设置到页面的data里面。访问地址的时候这串参数也已经传递上去了。

但!这里不是你想的那样!你会发现不论怎么样都不是预想的效果的。如果你在onload方法里的开头添加一句

dd.alert({userid});

结果就会很清楚。 ——页面加载完后,这个函数才执行!也就是说页面已经显示了,才会弹出框。这就是本质问题所在。

我们写在同一个页面的js里,获取userid的函数执行实际上是比页面加载来得慢的(虽然我们将方法写在onload()里面,按道理是在页面加载的时候就要处理完,但因为函数执行获取userid是需要先获取免登码,然后再请求到后端处理,处理完才返回结果。这个过程是有一定时间的,所以没办法在我们触发跳转事件后的第一时间就能获取到userid并设置到data里面。所以data里面的userid是没有值的!)

而如果我们用两个页面传参的方式,在login页面加载完后,获取到userid了,并设置到了data上去。这时把这个userid传过去First页面,在First.js里的onload()方法就不需要再请求了,只需要将获取到的userid设置到data里就行了。所以时间就同步了。

简单来说就是时间差导致的不同步问题。

以上观点只是我自己的想法,如果有错误的希望指出,感谢!

01-23 08:23