Vue _ 教程版 03

58 篇文章 4 订阅

目录

一、计算属性 - computed

二、侦听器 - watch

三、过滤器 - filters

四、混入 - Mixins

五、实例生命周期

六、网络请求

6.1、XmlHttpRequest 

6.2、Fetch

6.3、axios

图例 :


跳转链接 =>  Vue _ 教程版 01 基础

跳转链接 =>  Vue _ 教程版 02 指令

跳转链接 =>  Vue _ 教程版 04 组件

跳转链接 =>  Vue _ 教程版 05


一、计算属性 - computed

模板中放入太多的逻辑会让模板过重且难以维护,使用 计算属性 可以让模板变得简洁易于维护。计算属性 是基于它们的响应式 依赖 进行 缓存 的 ,计算属性 比较适合对 多个变量或者对象 进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化。

计算属性 定义在 Vue 对象中,通过 关键词 computed 属性对象 中定义一个个函数,并返回一个值,使用 计算属性 时和 data 中的数据使用方式一致

// 标准写法
computed: {
  get() {
    return this.xx
  },
  set(v) {
    this.xx = v
  }
}

// 简写 ( 常用 )
computed: {
  xx() {
    return this.xx
  }
}

<div id="app">
	<!-- 当多次调用 cfn 计算属性时只要里面的 num 值不改变,它会把第一次计算的结果
直接返回 , 直到 data 中的 num 值改变 计算属性 才会重新发生计算 -->
	<div>{{ cfn }}</div>
	<div>{{ cfn }}</div>
	<!-- 调用 methods 中的方法的时候  他每次会重新调用 , 消耗性能 -->
	<div>{{ fn() }}</div>
	<div>{{ fn() }}</div>
</div>
<script type="text/javascript">
  const vm = new Vue({
    el: '#app',
    data: {
      num: 10
    },
    // 方法
    methods: {
      fn() {
        console.log('methods')
        return this.num
      }
    },
    // 计算属性
    computed: {
      cfn() {
        console.log('computed')
        return this.num
      }
    }
  })
</script>

注:只要依赖的 数据源 不发生改变,我就调用1次,其它使用 缓存

计算属性 的 依赖项,可以是一对一,也可是一对多

购物车 案例 :

高阶函数 之 聚合运算 _ reduce


二、侦听器 - watch

使用 watch 来侦听 data 中数据的变化 , watch 中的属性一定是 data 中已经存在的数据。

当需要监听一个对象的改变时,普通的 watch 方法无法监听到对象内部属性的改变,只有 data 中的数据才能够监听到变化,此时就需要 deep 属性对象 进行 深度监听

// 标准
watch: {
  xx: {
    //immediate:true / false, // 此侦听器是否初始化时立即执行一次 true 是
    deep: true / false, // 如果观察的是一个对象则设置为 true
    handler(newVal, oldVal) {}
  }
}
// 简写
watch: {
  xx(newVal, oldVal) {}
  'xx.nn'(newVal, oldVal) {}
}

<div id="app">
  <input type="text" v-model='user.name'>
  <span>{{num_msg}}</span>
</div>
<script>
  const vm = new Vue({
    el: '#app',
    data: {
      num: '10',
      num_msg: '',
      user: {
        name: '张三'
      }
    },
    // 侦听器  1对1  依赖项只有一个
    watch: {
      num(newValue, oldValue) {
        // [^] : 非 : 表示 [^] 内的任意一个都不行
        // [^] =>写在中括号中,表示取反,不是0-9的数据则匹配成功
        if (/[^0-9]/.test(newValue)) {
          this.num_msg = '全数字'
        } else {
          this.num_msg = ''
        }
      },
      // 默认不会对于引用类型进行监听,除非你修改了引用地址
      // 监听对象中的具体字段的值的变化
      'user.name'(newVal, oldVal) {
        console.log(newVal)
      },
      // 标准版本
      user: {
        // 深度监听
        deep: true,
        handler(newVal, oldVal) {
          console.log(newVal)
        }
      },
    }
  })
</script>


三、过滤器 - filters

在数据被渲染之前,可以对其进行进一步处理,比如将 字符截取 或者将 小写统一转换为大写 等等,过滤器 本身就是一个 方法

过滤器 可以定义 全局 或 局部

<div id="app">
  <!-- 过滤器 -->
  <!-- 传递实参(5)给 len 形参 -->
  <h3>{{title | substr(5)}}</h3>
  <!-- 不传递参数 -->
  <h3>{{title | substr}}</h3>
</div>
<script>
  /* function fn() {
    console.log(arguments)
  }
  fn(1, 2, 3, 4, 5) */
  /* const fn = (...args) => {
    console.log(args)
  } */
  // 全局过滤器
  // 形参 len 设置一个 默认值
  Vue.filter('substr', (value, len = 10) => {
    if (value.length <= len) return value;
    return value.substr(0, len) + '...'
  })
  const vm = new Vue({
    el: '#app',
    data: {
      title: '这段时间娱乐圈可谓是抢占了头条,抖音,相继出现'
    }
  })
</script>


四、混入 - Mixins

混入( mixins )是一种分发 Vue 组件中 可复用功能 的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

混入分为:全局 ( Vue.mixin( { } ) ) 和 局部 ( 需在 Vue 实例中进行注册 )

JS 实现混入 : 

<!-- 2. 挂载 -->
  <div id="root">
    <h1>{{ name }}</h1>
    <h2>{{ showTitle() }}</h2>
  </div>
  <hr>
  <div id="root2">
    <h1>{{ name }}</h1>
    <h2>{{ showTitle() }}</h2>
  </div>
  <script>
    /* 全局混入
    此操作不需要在 Vue 实例中做任何操作
    混入中配置选项和 Vue 构造方法中的选项差不多一样的 , 但是有一项不一样
    混入中不能混入 el 配置
    混入中的 data 配置 , 一定要写成函数方式 , 且必须要返回一个对象 */
    Vue.mixin({
      data() {
        return {
          name: '张三 --- 全局混入'
        }
      },
      methods: {
        showTitle() {
          return '我是一个标题 --- 全局混入'
        }
      },
      // 生命周期
      mounted() {
        console.log('mounted --- 全局混入');
        this.uname = '--- mounted -- 李四 --- 全局混入'
      },
    })

    /* 局部混入 */
    let mixin = {
      data() {
        return {
          // 如果只有全局和局部 data 数据 , 以局部为主
          name: 'Jack --- 局部混入'
        }
      },
      methods: {
        showTitle() {
          return '我是一个标题 --- 局部混入'
        }
      },
      // 生命周期
      mounted() {
        console.log('mounted --- 局部混入');
      },
    }

    /* 3. 实例化 */
    const vm = new Vue({
      el: '#root',
      // 如果当前组件 data 中有对应的字段, 则以自己的为主
      data() {
        return {
          name: '小灰狼 - 1'
        }
      },
      methods: {
        // methods 混入的方案和 data 混入的方案是一样的
        showTitle() {
          return '我是一个标题 --- 本组件内'
        }
      },
      mounted() {
        console.log('mounted --- 本组件内' + this.uname);
      },
      // 注册 [局部混入]
      mixins: [mixin]
    })
    /* 3. 实例化 */
    const vm2 = new Vue({
      el: '#root2',
      // 如果当前组件 data 中有对应的字段, 则以自己的为主
      data() {
        return {
          name: '小灰狼 - 2'
        }
      }
    })
  </script>

<script>
  let o1 = { id: 1, fn() { console.log('o1') } }  // o1
  let o2 = { name: '张三', age: 20, fn() { console.log('o2') } } // o2
  // o1 = { ...o2, ...o1 }
  o1 = merge(o1, o2)
  o1.fn() 
  console.log(o1.name)  // 张三
  function merge(o1, o2) {
    let obj = { ...o1 }
    for (let key in o2) {
      if (typeof o2[key] === 'function') {
        if (o1[key]) {
          obj[key] = function () {
            // 此引用地址变成新的
            let f2 = o2[key]
            let f1 = o1[key]
            f1()
            f2()
          }
        }
      } else {
        obj[key] = o2[key]
      }
    }
    return obj
  }
</script>
<div id="app">
  <h3>{{title}}</h3>
  <button @click="click">点击事件</button>
</div>

<script type="module">
  import http from './js/http.js'
  // 混入生命周期,执行顺序 全局先执行 > 局部执行 > 组件内执行
  // 全局
  Vue.mixin({
    created() {
      // 通过自定义属性对当前的实例添加了,自定义属性
      this.$http = http;
      console.log('全局混入---created')
    }
  })

  // 局部混入
  // 混入 vue 配置选项中的大部份配置,只有 el 不能混
  // 混入时 data 配置选项一定要是 函数方式,且函数一定要返回一个 对象
  let mixinData = {
    data() {
      return {
        title: '你好混入'
      }
    },
    methods: {
      click() {
        console.log(111)
      }
    },
    // 混入生命周期,执行顺序 全局先执行 > 局部执行 > 组件内执行
    created() {
      console.log('局部混入---created')
    }
  }

  const vm = new Vue({
    el: '#app',
    data: {
      // 数据如果本组件中有配置则以 本组件 为主
      title: 'vue'
    },
    // 注册一下
    mixins: [mixinData],
    methods: {
      click() {
        console.log(this.$http);
        console.log(2222)
      }
    },
    created() {
      // console.log(this.$http);
      console.log('组件混入---created')
    }
  })
</script>
export default ({
  url,
  method = 'GET',
  data = {}
}) => {
  return new Promise((resolve, reject) => {
    let xhr = new XMLHttpRequest;
    xhr.open(method, url, true)
    if (method === 'post') {
      xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
      let postData = [];
      for (let key in data) {
        postData.push(`${key}=${data[key]}`)
      }
      xhr.send(postData.join('&'))
    } else {
      xhr.send(null)
    }
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4) {
        if ([200, 201, 202, 204].includes(xhr.status)) {
          let json = xhr.status != 204 ? JSON.parse(xhr.responseText) : {}
          resolve(json)
        } else {
          reject('fail')
        }
      }
    }
  })
}


五、实例生命周期

每个 Vue 实例 在被创建之前都要经过一系列的 初始化 过程 。例如需要设置 数据监听、编译模板、挂载实例 到 DOM、在数据变化时 更新 DOM 等。同时在这个过程中也会运行一些叫做 生命周期钩子的函数,给予用户机会在一些特定的场景下添加他们自己的代码。

beforeCreate

在实例初始化之后,数据观测和事件配置之前被调用 此时 datamethods 以及页面的 DOM 结构都没有初始化 什么都做不了 执行1次

created

实例创建完成后被立即调用 , 此时 data 和 methods 已经可以使用 但是页面还没有渲染出来 执行1次  用 this 对象

beforeMount

挂载开始之前被调用 此时页面上还看不到真实数据 只是一个模板页面而已  执行1 次

mounted

el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。 数据已经真实渲染到页面上 在这个钩子函数里面可以 进行数据请求 等  执行1次

beforeUpdate

数据更新时调用,页面上数据还是旧的  执行 n 次

updated

由于数据更新完毕,页面上数据已经替换成最新的 执行 n 次

beforeDestroy

实例销毁之前调用   执行1

destroyed

实例销毁之后调用     执行1

activated

keep-alive 组件 激活 时调用

deactivated

keep-alive 组件 停用 时调用

errorCaptured

捕获一个来自子孙组件的错误时被调用

<div id="app">
  <input type="text" v-model.number="num">
  <hr>
  <button @click="destroy">销毁当前组件</button>
</div>

<script>
  const vm = new Vue({
    el: '#app',
    data: {
      num: 100,
      timer: null,
    },
    methods: {
      destroy() {
        this.$destroy()
      }
    },
    // 由 Vue 提供,自动去执行的一系列的钩子函数,组件层面,有 8 个
    // 它能用 this,但是 this 中不能得到 data 和 methods 中数据和方法 初始化执行 只执行1次
    beforeCreate() {
      // console.log(this)
      console.log('beforeCreate', this.num)
    },
    // 数据已经监听完毕  只执行1次  可以写 网络请求
    created() {
      console.log('created', this.num)
    },
    // 数据和模板编译完成,还没有挂载到 dom 节点中之前执行 只执行1次  可以写 网络请求
    beforeMount() {
      console.log('beforeMount')
    },
    // 虚拟 dom 挂载到真实的 dom 中去了  只执行1次,可以写 网络请求 ( 推荐 )
    mounted() {
      console.log('mounted')
      // 执行计数器之前清空之前动画
      this.timer && clearInterval(this.timer)
      this.timer = setInterval(() => {
        console.log(111)
      }, 1000);
    },
    // 数据修改之前  执行n次
    beforeUpdate() {
      console.log('beforeUpdate')
    },
    // 数据修改之后 执行N次  如果要想得到最后的真实的修改数据,在此钩子函数中获取
    updated() {
      console.log('updated', this.num)
    },
    // 销毁之前,一般会在此处对于计算器等进行清理处理
    beforeDestroy() {
      // 离开之前清空动画
      this.timer && clearInterval(this.timer)
      
      console.log('beforeDestroy')
    },
    destroyed() {
      console.log('destroyed')
    }
  })
</script>

Vue 生命周期 图解 :



面试点 : 在 created 和 mounted 里面发送请求效果上有啥区别呢 ?


六、网络请求

6.1、XmlHttpRequest 

var xmlhttp = new XMLHttpRequest()
xmlhttp.onreadystatechange = function () {
  if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
    console.log(xmlHttp.responseText)
  }
}
// GET
xmlhttp.open("GET", url, true)
xmlhttp.send(null)
// POST
// xhr.open('POST', 'url', true);
// xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
// var data = new FormData();
//data.append('user', 'person');
//xmlhttp.send(data)

6.2、Fetch

使用 Fetch - Web API 接口参考 | MDN

Fetch 是新的 ajax 解决方案 Fetch 会返回 Promise 对象 。fetch 不是 ajax 的进一步封装,而是原生 js ,没有使用 XMLHttpRequest 对象 。

参数说明

1、第一个参数是 URL :

2、第二个设置 请求的 参数 ,是可选参数

3、返回使用了 Promise 来处理 结果 / 回调

fetch( url, options ).then( res=>res.json()/text()).then(ret=>console.log(ret) )

 Fetch 它给我们提供了很多的方法,如 POST,GET,DELETE,UPDATE,PATCH 和 PUT 等 。默认的是 GET 请求,可以在设置请求参数中指定请求方法,通过 method 来设置

// get 请求
// 通过 url 表达式来传递数据
fetch('http://xxx/?id=123')
  .then(res => res.json())
  .then(data => console.log(data))

// post 标准提交
fetch('http://xxxx/post', {
  method: 'post',
  body: 'uname=lisi&pwd=123',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
}).then(res => res.json()).then(data => console.log(data))

// post 提交 json 数据
fetch('http://localhost:3000/books', {
  method: 'post',
  body: JSON.stringify({
    uname: 'lisi',
    pwd: '123'
  }),
  headers: {
    'Content-Type': 'application/json'
  }
}).then(res => res.json()).then(data => console.log(data))
// 有文件上传时使用
let formData = new FormData()
formData.append('id', 2000)
formData.append('name', 'zhangsan')
fetch('http://localhost:3000/api/users', {
  method: 'POST',
  // formData数据
  body: formData,
  headers: {
    'content-type': 'application/x-www-form-urlencoded'
  }
})
  .then(res => res.json())
  .then(data => console.log(data))
<script type="module">
  import fetchApi from './js/fetch.js'

  const vm = new Vue({
    el: '#app',
    data: {
      users: []
    },
    // 发起网络请求
    mounted() {
      let url = 'http://localhost:3000/api/users'
      // fetchApi({ url }).then(data => console.log(data))
      fetchApi({ url, method: 'POST', data: { id: 200, name: 'aaa' } }).then(data => console.log(data))
    }
  })
</script>

封装 : 

export default ({
  url,
  method = 'GET',
  data = null,
}) => {
  // 请求配置
  let options = {
    method
  }
  // data 不为空时,它就是 post 请求
  if (data) {
    options = {
      ...options,
      body: JSON.stringify(data),
      headers: {
        'content-type': 'application/json'
      }
    }
  }
  return fetch(url, options)
    .then(res => res.json())
    .then(data => data)
}

6.3、axios

文档:使用说明 · Axios 中文说明 · 看云

Axios 是一个基于 Promise 的 HTTP 库,可以用在 浏览器  node.js 中。能拦截 请求 和 响应自动转换 JSON 数据 axios 也是 Vue 作者推荐使用的 网络请求库

 使用语法 :

# GET
## 方法1
axios.get('/user?ID=12345').then(res=>{})
## 方法2
axios.get('/user', {
  params: {
    ID: 12345
  }
}).then(res=>{})

# POST
axios.post('/user', {
  firstName: 'aa',
  lastName: 'bb'
}).then(res=>{})

# 标准写法
axios({
  method: 'post',
  url: '/user/12345',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'},
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
})

axios 全局配置

#  配置公共的 域名地址

axios.defaults.baseURL = 'https://api.example.com';

#  配置 超时时间  毫秒数 ( 0 表示无超时时间 )

axios.defaults.timeout = 1000;

#  配置公共的 请求头

axios.defaults.headers.token = 'token值';

get 请求 :

<!-- axios专门用于网络请求所有的库 -->
<script src="./js/axios.js"></script>
<script>
// 创建一个私有的实例,通过实例来完成操作请求
/* const server = axios.create({
  // 超时时间
  timeout: 10000,
  // 请求的基础路径  域名
  baseURL: 'http://localhost:3000',
  // 设置头信息
  headers: {
	a: 'aaaa'
  }
}) */

// 统一给axios设置
/* axios.defaults.timeout = 10000
axios.defaults.baseURL = 'http://localhost:3000'
axios.defaults.headers.a = 'admin' */

// 拦截器   切面编程   (中间件)
// 请求拦截器
axios.interceptors.request.use(config => {
  // 统一设置请求域名地址
  config.baseURL = 'http://localhost:3000'
  // 超时时间
  config.timeout = 1000
  // 设置头信息
  // config.headers.token = 'mytoken login'

  return config;
}, err => Promise.reject(err))

axios.interceptors.request.use(config => {
  // 统一设置请求域名地址
  // config.baseURL = 'http://localhost:3000'
  // 设置头信息
  config.headers.token = 'mytoken login222'

  return config;
}, err => Promise.reject(err))

// 响应拦截器
axios.interceptors.response.use(response => {
  return response.data
}, err => {
  // 可以在响应拦截器中统一去处理,请求异常
  alert('请求失败了,请重新请求一次')
  return Promise.reject(err)
});
const vm = new Vue({
  el: '#app',
  data: {
  },
  mounted() {
	// let url = 'http://localhost:3000/api/users'
	let url = '/api/users'
	// axios.get/post/put/delete
	// axios.get(url,config) // config可以设置头信息
	// axios.post(url,data,config)
	// axios.put(url,data,config)
	// axios.delete(url,data,config)

	// axios.get(url).then(res => console.log(res.data))
	// axios.get(url).then(res => console.log(res))
	// server.get(url).then(res => console.log(res.data))

	// post提交
	// axios.post(url, { id: 1, name: 'aaaa' }).then(res => console.log(res.data))

	// axios直接用
	// axios({
	//   url,
	//   method:'get',
	//   data:{}
	// }).then(res => console.log(res))
  }
})
</script>


图例 :


跳转链接 =>  Vue _ 教程版 01 基础

跳转链接 =>  Vue _ 教程版 02 指令

跳转链接 =>  Vue _ 教程版 04 组件

跳转链接 =>  Vue _ 教程版 05

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值