|  | 本文参考孙卫琴,杜聚宾所创作的 <<精通Vue.js: Web前端开发技术详解>>一书 
 当用户在浏览器端进行路由导航时,有些目标路由的组件需要从服务器端抓取数据,再把这些数据显示到网页上。抓取数据有两种方式:
 (1)导航后抓取:在导航完成后,在目标路由的组件的生命周期函数中抓取数据。在抓取的过程中,可以在网页上显示“正在加载中...”的提示信息。
 (2)导航前抓取:先在导航守卫函数beforeRouteEnter()和beforeRouteUpdate()中抓取数据,接下来再进行导航。
 以上两种方式都能完成抓取任务,到底选用哪一种,取决于开发人员的喜好以及开发团队的要求。
 1.导航后抓取例程1的ItemPostFetch.vue定义了ItemPostFetch组件,在它的created()钩子函数中,调用$watch()函数监听$route.params变量,如果该变量发生更新,就会执行fetchData()方法。该$watch()函数的第三个参数{ immediate: true }确保在ItemPostFetch组件的初始化阶段也会执行一次fetchData()方法。
 fetchData()方法负责抓取数据,在实际应用中,会通过Ajax请求到服务器端抓取数据,本方法做了简化,通过setTimeOut()函数来模拟耗时的抓取数据的行为。
 
 例程1  ItemPostFetch.vue
 
 
 | <template> <div>
 <div v-if="isLoading" >商品数据加载中...</div>
 <div v-if="isError" >商品数据加载失败</div>
 <div v-if="isReady">
 <p>商品ID: {{item.id}}</p>
 <p>商品名字: {{item.title }} </p>
 <p>商品描述: {{item.desc}}</p>
 </div>
 </div>
 </template>
 
 <script>
 import Items from '@/assets/items'  //引入Item数据
 export default {
 data() {
 return {
 item: {},
 isLoading: false,
 isReady: null,
 isError: null
 }
 },
 created() {
 //监听$route.params,如果发生更新,就调用fetchData()方法
 this.$watch(
 () => this.$route.params,
 () => {
 this.fetchData()
 },
 //确保在初始化组件时也调用一次fetchData()方法
 { immediate: true }
 )
 },
 methods: {
 fetchData() {
 this.isReady = null
 this.isError=null
 this.isLoading = true
 //模拟耗时的抓取数据行为,在实际应用中会到服务器端抓取数据
 setTimeout(
 ()=>{
 this.item=Items.find(
 (item)=>item.id==this.$route.params.id
 )
 if(this.item){
 //如果存在与id匹配的商品数据,就显示商品数据
 this.isLoading=false
 this.isReady=true
 }else{
 //如果不存在与id匹配的商品书,就显示错误信息
 this.isLoading=false
 this.isError=true
 }
 },2000)     //延迟2秒后执行数据抓取
 }
 }
 }
 </script>
 | 
 在index.js中,为ItemPostFetch组件设置如下路由:
 
 
 | { path: '/postfetch/:id',
 component: ItemPostFetch
 }
 | 
 通过浏览器访问“http://localhost:8080/#/postfetch/1”,会看到网页上首先显示“商品数据加载中.”,接下来再显示id为1的商品信息。
 通过浏览器访问“http://localhost:8080/#/postfetch/5”,会看到网页上首先显示“商品数据加载中.”,接下来再显示“商品数据加载失败”。
 2.导航前抓取在例程2的ItemPreFetch.vue中定义了ItemPreFetch组件。在beforeRouteEnter()和beforeRouteUpdate()导航守卫函数中都会通过fetchData()函数来抓取数据。这个fetchData()是一个独立的函数,不属于ItemPreFetch组件。fetchData()函数有一个作为回调函数的callback参数,当抓取数据完毕后,callback回调函数会把item变量和isError变量赋值给ItemPreFetch组件的item变量和isError变量。由于在beforeRouteEnter()函数中不能通过this关键字来访问ItemPreFetch组件,因此通过next()函数来为ItemPreFetch组件的item变量和isError变量赋值。
 
 例程2  ItemPreFetch.vue
 
 
 | <template> <div>
 <div v-if="isError" >商品数据加载失败</div>
 <div v-if="! isError">
 <p>商品ID: {{item.id}}</p>
 <p>商品名字: {{item.title }} </p>
 <p>商品描述: {{item.desc}}</p>
 </div>
 </div>
 </template>
 
 <script>
 import Items from '@/assets/items'   //引入Item数据
 
 function  fetchData(id,callback) {
 let isError=null
 let item=null
 //模拟耗时的抓取数据行为,在实际应用中会到服务器端抓取数据
 setTimeout(
 ()=>{
 item=Items.find(
 (item)=>item.id==id
 )
 if(item){
 isError=false
 }else{
 isError=true
 }
 callback(item,isError)
 },2000)     //延迟2秒后执行数据抓取
 }
 
 export default {
 data() {
 return {
 item: {},
 isError: null
 }
 },
 beforeRouteEnter(to, from, next) {
 fetchData(to.params.id,
 (item, isError) => {
 next(vm => {
 vm.item=item
 vm.isError=isError
 })
 }
 )
 },
 beforeRouteUpdate(to) {
 fetchData(to.params.id,
 (item, isError) => {
 this.item=item
 this.isError=isError
 }
 )
 }
 }
 </script>
 | 
 beforeRouteEnter()函数如果不使用next参数,还可以改写为:
 
 
 | beforeRouteEnter(to) { fetchData(to.params.id,
 (item, isError) => {
 return vm => {
 vm.item=item
 vm.isError=isError
 }
 }
 )
 }
 | 
 在index.js中,为ItemPreFetch组件设置如下路由:
 
 
 | { path: '/prefetch/:id',
 component: ItemPreFetch
 }
 | 
 通过浏览器访问“http: //localhost:8080/#/prefetch/1”,会看到网页首先停留在原来的页面,接下来再显示id为1的商品信息。
 通过浏览器访问“http: //localhost:8080/#/prefetch/5”,会看到网页首先停留在原来的页面,接下来再显示“商品数据加载失败”。
 
 
 
 程序猿的技术大观园:www.javathinker.net
 |  |