axios、fecth、vue-resource、watch、computed、mixins、原理

本文围绕Vue框架展开,介绍了框架级的数据请求方式,如axios和fetch,并对二者进行比较,还讲述了Vue数据请求的发展。同时,讲解了watch、计算属性computed的使用及区别,mixins的应用。最后深入剖析了Vue的数据驱动、双向数据绑定等底层原理。

框架级的数据请求

1.axios

( 第三方库 — 别人封装好的库 )

当我们引入 axios cdn之后,就会全局暴露一个 axios 对象

  • 案例:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> axios </title>
  <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
  <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
  <style>
    button{
      margin: 10px;
    }
  </style>
</head>
<body>
  <div id="app">
    <button @click = "getData"> get - mock - json </button>
    <button @click = "get_be_data"> get - backend online- api </button>
    <button @click = "get_myself_php_data"> get - myself - php -api </button>
    <button @click = "postData"> post </button>
  </div>
</body>
<script>
  /* 
    当我们引入 axios cdn之后,就会全局暴露一个 axios 对象
  */
  new Vue({
    el: '#app',
    methods: {
      getData () {
        //进行get请求
        // axios.get()    -- $.get()
        // axios.post()    ---$.post()
        // axios(options)      -- $.ajax(options)

        // var p = axios({
        //   url: './data/data.json'
        // })

        // console.log( p )  Promise对象

        axios({
          url: './data/data.json',
          method: 'get',//默认就是get请求
        })
          .then( res => console.log( res ))
          .catch( error => conosle.log( error ))
 

      },
      get_myself_php_data () {
        axios({
          url: 'http://localhost/get.php',
          params: {
            a: 1,
            b: 2
          }
        })
          .then( res => console.log( res ))
          .catch( error => console.log( error ))
      },
      get_be_data () {
        // 跨域请求线上数据 - 卖座
        axios({
          url: 'https://m.maizuo.com/gateway',
          headers: {
            'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.0.4","e":"154549400038873748996477"}',
            'X-Host': 'mall.film-ticket.film.list'
          },
          params: {
            cityId: 330100,
            pageNum: 1,
            pageSize: 10,
            type: 1,
            k: 7675918
          }
        })  
          .then( res => console.log( res ))
          .catch( error => console.log( error ))

      },
      postData () {
        /*        
          post请求官网案例有些坑  会报错 跨域问题
          axios({
                url: 'http://localhost/post.php',
                method: 'post',
                data: {
                  a: 2,
                  b: 2
                }
              })
                .then( res => console.log( res ))
                .catch( error => console.log( error ))
        */
        var params = new URLSearchParams() //得到params对象,用来接收参数
        // params.append( key, value )  key就是参数名,value就是参数值
        params.append( 'a', 2 )
        params.append( 'b', 2 )
        axios({
          url: 'http://localhost/post.php',
          method: 'post',
          headers: {
            'Content-Type': "application/x-www-form-urlencoded" //请求头设置为表单提交的请求头
          },
          data: params
        })
          .then( res => console.log( res ))
          .catch( error => console.log( error ))
      }
    }
  })
</script>
</html>

2.fecth

( javascript 原生提供 )

代码举例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> fetch </title>
  <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
</head>
<body>
  <div id="app">
    <button @click = "getData"> get </button>
    <button @click = "postData"> post </button>
  </div>
</body>
<script>
  /* 
    fetch是原生javascript提供的 , 所以它 可以当做全局变量使用 ,它是挂载在window对象身上的
  */
  new Vue({
    el: '#app',
    methods: {
      getData () {
        fetch('./data/data.json')
          .then( res => res.json() ) //对json数据进行格式化
          .then( data => console.log( data ) ) // 这里的data就是格式化后的数据
          .catch( error => console.log( error ))
        // fetch('https://m.maizuo.com/gateway?cityId=330100&pageNum=1&pageSize=10&type=1&k=7675918')
      },
      postData () {
        fetch( 'http://localhost/post.php',{
          method: 'post',
          headers: new Headers({
            'Content-Type': 'application/x-www-form-urlencoded' // 指定提交方式为表单提交
          }),
          body: new URLSearchParams([["a", 1],["b", 2]]).toString() 
        })
          .then( res => res.text() )//格式化文本
          .then( data => console.log( data ))
          .catch( error => console.log( error ))
      }
    }
  })
</script>
</html>

fetch总结

  • fetch要手动进行一次数据格式化,但是axios是内部进行了数据的格式化
  • fetch get 方法请求数据,参数要直接连接在url上
  • fetch 格式化数据 有三种 处理方法
    • .json() 格式化 json 类型数据, 将 json类型 string 转换成 json 对象
    • .text() 格式化文本
    • .blob() 格式化二进制数据
  • fetch 如果按照官网文档书写post请求,也有坑, 携带数据出现了问题
  • fetch post处理
    • 设置请求头
    • 通过 new URLSearchPrams 来携带参数

3.axios与fetch比较

axios 和 fetch 没有jsonp 数据请求类型的

  • axios 和 fetch 都是promise
  • axios会对我们请求来的结果进行再一次的封装( 让安全性提高 )

4.vue这边的数据请求的发展

  • vue-resource ( Vue 以前自己封装使用的请求类库 ) ,但是 vue-resource作者已经放弃更新了
  • vue-resource 作者推荐我们使用 axios
  • vue-resource 用法 和 axios 相似度 90% +
  • vue2.0我们基本上使用的都是 fetch / axios
  • vue-resource 是有jsonp的
  • vue-resource 如果在vue中使用,是挂载当前的 实例( 组件 ) 的$http属性身上的
    • 举例 this. h t t p ( o p t i o n s ) t h i s . http( options ) this. http(options)this.http.get() this.$http.post

5.watch

  1. 作用
  • 用来监听data中定义的数据,当data中定义的数据发生了变化,那么watch中的key就会触发
  • watch是一个对象
    watch: {}
  • watch中可以设置多个类型的键值
  1. 使用方式( 重点 )
  • 方法
watch: {
      fn () {}
    }
  • 对象: ( 深度监听 )
watch: {
      fn: {
        handler(){},
        deep: true
      }
    }

案例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> watch </title>
  <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
</head>
<body>
  <div id="app">
    <div class="container">
      <div class="row">
        <form>
            <div class="form-group">
                <label for="exampleInputEmail1"> 姓氏 </label>
                <input 
                  v-model = "firstName"  
                type="text" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="请输入姓氏:">
            </div>
            <div class="form-group">
              <label for="exampleInputPassword1"> 名字 </label>
              <input 
                v-model = "lastName"  
              type="text" class="form-control" id="exampleInputPassword1" placeholder=" 请输入名字 ">
            </div>
            <div class="form-group">
              <label for="exampleInputPassword1"> 全名 </label>
              <input 
                v-model = "fullName"  
              type="text" class="form-control" id="exampleInputPassword1" placeholder="  ">
            </div>
        </form>
      </div>
    </div>
  </div>
</body>
<script>
  new Vue({
    el: '#app',
    data: {
      firstName: '',
      lastName: '',
      fullName: ''
    },
    watch: {
      //1. watch中可以设置方法,方法名就是data中的 key  
      firstName ( val ) {
        console.log( val ) //改变后的值
        this.fullName = val + this.lastName
      },
      lastName ( val ) {
        this.fullName = this.firstName + val
      }

    }
  })
</script>
</html>

案例2:

<script>
  /*  
    watch 的深度监听
  */
  new Vue({
    el: '#app',
    data: {
      firstName: '',
      lastName: '',
      fullName: '',
      name: {
        xiaoming: {
          xiaoming: {
            xiaoming: 'xiaomign'
          }
        }
      }
    },
    watch: {
      //1. watch中可以设置方法,方法名就是data中的 key  
      firstName ( val ) {
        console.log( val ) //改变后的值
        this.fullName = val + this.lastName
      },
      lastName: {
        handler ( val ) { //处理程序
          this.fullName = this.firstName + val
        },
        deep: true
      }

    }
  })
</script>

6.计算属性computed

  1. 使用方式
    • 里面存放方法
      computed: {
        fn () {
          return ''   //必须要有返回值
        }
      }
    
    • 里面存放对象
      computed: {
        newName: {
          get () {
            return '' //get里面要有return
          },
          set ( val ) { //val就是修改后的值
    
          }
        }
      }
    
<script>
  new Vue({
    el: '#app',
    data: {
      firstName: '',
      lastName: '',
    },
    computed: {
      fullName () {
        return this.firstName + this.lastName
      }
    }
  })
</script>
<script>
  new Vue({
    el: '#app',
    data: {
      firstName: '',
      lastName: '',
    },
    computed: {
      fullName: {
        get () {
          return this.firstName + this.lastName
        },
        set ( val ) {
          this.firstName = val.slice(0,2)
          this.lastName = val.slice(2)
        }
      }
    }
  })
</script>
- 注意: 上面的get,set我们统一起了个名字叫做: 存储器,别人也叫getter/setter
- get set 这两者, 对象中有,类里面也有
- **get set 是计算属性的    这个理解是错的**

7.watch 与 computed 比较

  1. watch是用来监听某一个数据的,当数据发生改变是,watch就会自动触发,然后我们可以进行一些任务
  2. computed是为了暴露一个全局变量,这个全局变量是经由一定逻辑产生的
  3. 什么时候选择 watch ? 什么是选择 computed ? 什么时候选择 methods?
  • 数据量较大,并且有异步操作我们选择 watch 应用场景: 上拉加载,下拉刷新
  • computd的使用满足两个就可以了
    • 暴露一个类似全局变量的数据
    • 可以进行逻辑的处理
  • methods的使用: 事件程序程序 ( 用户交互 )

8.mixins ( 了解 )

实际意义:将组件的选项抽离出去,单独管理,复用

  • 有两种使用形式
    • 局部混入
    • 全局混入(一般不使用)

案例:

局部混入:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
</head>
<body>
  <div id="app">
    <button @click = "add"> add </button>
    <button @click = "aa">  aa </button>
  </div>
</body>
<script>

  var mixinObj = {
    methods: {
      add () {
        alert ( 'add' )
      }
    }
  }

  new Vue({
    el: '#app',
    data: {},
    mixins: [ mixinObj ], //局部混入
    methods: {
      aa () {
        alert( 'aa' )
      },
      add () { // 如果实例中方法名和mixins中的方法名相同,那么实例中的触发
        console.log( '实例中add' )
      }
    },
    watch: {},
    computed:{}
  })
</script>
</html>
全局混入:
<script>
/* 
  全局的混入  :  Vue.mixin({})       不建议使用
 */

  Vue.mixin({
    methods: {
      add () {
        alert( 'add' )
      }
    }
  })

  new Vue({
    el: '#app',
    data: {},
  })
</script>

原理( 很重要 )

  1. 数据驱动
    当数据发生改变时,视图也会进行更新,这叫做数据驱动,也就是数据驱动视图
  2. 深入响应式原理
    数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新
  3. 双向数据绑定原理
    当我们使用 v-model 指令绑定了表单元素时,那么我们可以在视图直接获得数据,当视图发生改变时,数据也会进行更新

综上: 三者都是应用了同一个底层原理,这个底层原理由es5的 Object.defineProperty 属性来提供

  • vue中底层原理的实现主要是依赖 存储器( getter/setter )

  • 我们利用了数据劫持和事件的发布订阅来实现双向数据绑定,当我们在vue data选项中定义数据时,vue会通过观察者对象( observer )将data选项中的所有key,经过Object.defineProperty 的getter 和setter进行设置,当我们通过 v-model指令绑定元素是, 自动触发getter,getter会返回一个初始值,这样我们在视图中就可以看到数据了,当视图中内容改变时,会触发setter,setter会通知vue,视图已经进行了更新,vue会重新生成 虚拟DOM , 继而通过 新旧 虚拟DOM 对比, 生成patch对象,再将patch对应渲染到视图中

Vue.set/this.$set 的原理( 数组的下标和length不响应 )

底层:Object.assign

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值