Vue 中的知识点

56 篇文章 4 订阅

目录

Vue中的侦听器(watch)

Vue中的过滤器(filter)

Vue中的生命周期

Vue中的网络请求

ajax、axios、fetch的区别

axios 使用方法

axios 封装代码(直接使用)

Vue中的组件

全局组件

局部组件

组件之间的数据传递

Props(父→子)

自定义事件(子→父)

自定义组件的 v-model


Vue中的侦听器(watch)

watch 概述

监测 Vue 实例变化的一个表达式或方法。回调函数得到的参数为新值和旧值,用一个函数取代。

简洁的说:watch 的作用可以监控一个值的变换,并调用因为变化需要执行的方法。可以通过watch 动态改变关联的状态。

普通监听

<!-- 普通监听 -->
<div id="app">
  <input type="text" v-model="num">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
  new Vue({
    el: '#app',
    data: {
      num: ''
    },
    watch: {
      num(newVal, oldVal) {
        // 监听 num 属性的数据变化
        // 作用 : 只要 num 的值发生变化,这个方法就会被调用
        // 第一个参数 : 新值
        // 第二个参数 : 旧值, 之前的值
        console.log('oldVal:', oldVal)
        console.log('newVal:', newVal)
      }
    }
  })
</script>

 immediate(立即处理 进入页面就触发)

<!-- immediate(立即处理 进入页面就触发) -->
<div id="app">
  <input type="text" v-model="num">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
  new Vue({
    el: '#app',
    data: {
      num: 1
    },
    watch: {
      num: {
        // 数据发生变化就会调用这个函数  
        handler(newVal, oldVal) {
          console.log('oldVal:', oldVal)
          console.log('newVal:', newVal)
        },
        // 立即处理 进入页面就触发
        immediate: true
      }
    }
  })
</script>

 deep(深度监听)

对象和数组都是引用类型 ,引用类型变量存的是地址,地址没有变,所以不会触发 watch 。这时我们需要进行深度监听,就需要加上一个属性 deep,值为 true

<!-- 深度监听 -->
<div id="app">
  <input type="button" value="更改名字" @click="change">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
  new Vue({
    el: '#app',
    data: {
      food: {
        id: 1,
        name: '土豆'
      }
    },
    methods: {
      change() {
        this.food.name = '西红柿'
      }
    },
    watch: {
      // 第一种方式:监听整个对象,每个属性值的变化都会执行 handler
      // 注意:属性值发生变化后,handler 执行后获取的 newVal 值和 oldVal 值是一样的
      food: {
        // 每个属性值发生变化就会调用这个函数
        handler(newVal, oldVal) {
          console.log('oldVal:', oldVal)
          console.log('newVal:', newVal)
        },
        // 立即处理 进入页面就触发
        immediate: true,
        // 深度监听 属性的变化
        deep: true
      },
      // 第二种方式:监听对象的某个属性,被监听的属性值发生变化就会执行函数
      // 函数执行后,获取的 newVal 值和 oldVal 值不一样
      'food.name'(newVal, oldVal) {
        console.log('oldVal:', oldVal) // 土豆
        console.log('newVal:', newVal) // 西红柿
      }
    }
  })
</script>

Watch 和 computed 的区别 :

Watch

    watch 用于观察和监听页面上的 vue 实例,当你需要在数据变化响应时,执行异步操作,或高性能消耗的操作,那么 watch 为最佳选择

computed

    可以关联多个实时计算的对象,当这些对象中的其中一个改变时都会触发这个属性

    具有缓存能力,所以只有当数据再次改变时才会重新渲染,否则就会直接拿取缓存中的数据。


Vue中的过滤器(filter)

过滤器的写法

首先,过滤器可在 new Vue 实例前注册全局的,也可以在组件上写局部。

全局过滤器:

Vue.filter('globalFilter', function (value) {

  return value + "!!!"

})

 组件过滤器(局部):

上面有种写法有个需要注意的问题:全局注册时是 filter ,没有 s 的。而组件过滤器是 filters ,是有 s 的,这要注意了,虽然你写的时候没有 s 不报错,但是过滤器是没有效果的

过滤器的使用方法 : 

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:

<!-- 在双花括号中 -->
{{ message | capitalize }}
 
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>

Vue中的生命周期

一、vue 的生命周期是什么

    vue 每个组件都是独立的,每个组件都有一个属于它的生命周期,从一个组件 创建、数据初始化、挂载、更新、销毁 ,这就是一个组件所谓的 生命周期 。在组件中具体的方法有:

 具体如下图:

 二、vue 生命周期的在项目中的执行顺序

...

data() {
  return {
    rendered: false,
  }
}

...

1. beforeCeate() {
  console.log(this.rendered); // undefined  
}

2. created() {
console.log(this.$el);         //undefined
console.log(this.rendered);    // false
}

3. beforeMount() {
console.log(this.$el);        //undefined
}

4. mounted() {
console.log(this.$el);
}

5. beforeDestroy() {
console.log(this.$el);
console.log(this.rendered);
}

6. destroyed() {
console.log(this.$el);
console.log(this.rendered);
}

三、vue 中内置的方法 属性和 vue 生命周期的运行顺序 :

( methods、computed、data、watch、props )

props => methods => data => computed => watch


Vue中的网络请求

ajax、axios、fetch的区别

ajax

$.ajax({
  type: 'POST',
  url: url,
  data: data,
  dataType: dataType,
  success: function () {},
  error: function () {}
});

  传统 Ajax 指的是 XMLHttpRequest(XHR),最早出现的发送后端请求技术,隶属于原始 js 中,核心使用 XMLHttpRequest 对象,多个请求之间如果有先后关系的话,就会出现回调地狱。

JQuery ajax 是对原生 XHR 的封装,除此以外还增添了对 JSONP 的支持。经过多年的更新维护,真的已经是非常的方便了,优点无需多言;如果是硬要举出几个缺点,那可能只有:

1.本身是针对 MVC 的编程, 不符合现在前端 MVVM 的浪潮
2.基于原生的 XHR 开发,XHR 本身的架构不清晰。
3.JQuery 整个项目太大,单纯使用 ajax 却要引入整个 JQuery 非常的不合理
(采取个性化打包的方案又不能享受 CDN 服务)
4.不符合关注分离( Separation of Concerns )的原则
5.配置和调用方式非常混乱,而且基于事件的异步模型不友好。

axios

// axios
axios({
    method: 'post',
    url: '/user/1234',
    data: {
      firstName: '张',
      lastName: '思瑞'
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

axios 是一个基于 Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生 XHR 的封装,只不过它是 Promise 的实现版本,符合最新的 ES 规范,它本身具有以下特征:

1. 从浏览器中创建 XMLHttpRequest
2. 支持 Promise API
3. 客户端支持防止 CSRF
4. 提供了一些并发请求的接口(重要,方便了很多的操作)
5. 从 node.js 创建 http 请求
6. 拦截请求和响应
7. 转换请求和响应数据
8. 取消请求
9. 自动转换 JSON 数据

fetch 

// fetch
fetch('http://example.com/movies.json')
  .then(function (response) {
    return response.json();
  })
  .then(function (myJson) {
    console.log(myJson);
  });

一、fetch 优势:

1. 语法简洁,更加语义化
2. 基于标准 Promise 实现,支持 async/await
3. 同构方便,使用 isomorphic-fetch
4. 更加底层,提供的 API 丰富(request, response)
5. 脱离了 XHR ,是 ES 规范里新的实现方式

二、fetch 存在问题 :

1. fetch 是一个低层次的 API ,你可以把它考虑成原生的 XHR ,
所以使用起来并不是那么舒服,需要进行封装。
2. fetch 只对网络请求报错,对 400,500 都当做成功的请求,
服务器返回 400,500 错误码时并不会 reject,
只有网络错误这些导致请求不能完成时,fetch 才会被 reject。
3. fetch 默认不会带 cookie ,需要添加配置项:
  fetch(url, {credentials: 'include'})
4. fetch 不支持 abort ,不支持超时控制,使用 setTimeout 及 Promise.reject 的
实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费
5. fetch 没有办法原生监测请求的进度,而 XHR 可以

axios 使用方法

1、基本用法

安装指令  =>  $   cnpm i axios --save 

在 main.js 中引入 axios

import axios from 'axios'
Vue.prototype.$axios = axios

在组件中使用 axios

// 在组件中使用 axios
export default {
  mounted() {
    this.$axios.get('/goods.json').then(res => {
      console.log(res.data);
    })
  }
}

2、axios 请求方法

axios可以请求的方法:

  • get: 获取 数据,请求指定的信息,返回实体对象
  • post:向指定资源 提交 数据( 例如表单提交或文件上传 )
  • put:更新数据,从客户端向服务器传送的数据取代指定的文档的内容
  • patch:更新数据,是对 put 方法的补充,用来对已知资源进行局部更新
  • delete:请求服务器 删除 指定的数据

2.1、get 请求

 示例代码 :

//方法一,请求格式类似于 http://localhost:8080/goods.json?id=1
this.$axios.get('/goods.json', {
  params: {
    id: 1
  }
}).then(res => {
  console.log(res.data);
}, err => {
  console.log(err);
})

//方法二
this.$axios({
  method: 'get',
  url: '/goods.json',
  params: {
    id: 1
  }
}).then(res => {
  console.log(res.data);
}, err => {
  console.log(err);
})

2.2、post 请求

post 请求一般分为两种类型

  • form-data 表单提交,图片上传、文件上传时用该类型比较多
  • application / json 一般是用于 ajax 异步请求

示例代码 :

// 2.2、post 请求
//方法一
this.$axios.post('/url', {
  id: 1
}).then(res => {
  console.log(res.data);
}, err => {
  console.log(err);
})

//方法二
$axios({
  method: 'post',
  url: '/url',
  data: {
    id: 1
  }
}).then(res => {
  console.log(res.data);
}, err => {
  console.log(err);
})

//form-data请求
let data = {
  //请求参数
}

let formdata = new FormData();
for (let key in data) {
  formdata.append(key, data[key]);
}

this.$axios.post('/goods.json', formdata).then(res => {
  console.log(res.data);
}, err => {
  console.log(err);
})

2.3、put 和 patch 请求

示例代码 :

// put 请求
this.$axios.put('/url', {
  id: 1
}).then(res => {
  console.log(res.data);
})

// patch 请求
this.$axios.patch('/url', {
  id: 1
}).then(res => {
  console.log(res.data);
})

2.4、delete 请求

示例代码 :

// 2.4、delete 请求
// 参数以明文形式提交
this.$axios.delete('/url', {
  params: {
    id: 1
  }
}).then(res => {
  console.log(res.data);
})

// 参数以封装对象的形式提交
this.$axios.delete('/url', {
  data: {
    id: 1
  }
}).then(res => {
  console.log(res.data);
})

//方法二
axios({
  method: 'delete',
  url: '/url',
  params: {
    id: 1
  },    //以明文方式提交参数
  data: {
    id: 1
  }     //以封装对象方式提交参数
}).then(res => {
  console.log(res.data);
})

3、并发请求

并发请求:同时进行多个请求,并统一处理返回值

示例代码 :

// 3、并发请求
this.$axios.all([
  this.$axios.get('/goods.json'),
  this.$axios.get('/classify.json')
]).then(
  this.$axios.spread((goodsRes, classifyRes) => {
    console.log(goodsRes.data);
    console.log(classifyRes.data);
  })
)

4、axios 实例

4.1、创建 axios 实例

示例代码 :

// 4.1、创建 axios 实例
let instance = this.$axios.create({
  baseURL: 'http://localhost:9090',
  timeout: 2000
})
instance.get('/goods.json').then(res => {
  console.log(res.data);
})

可以同时创建多个 axios 实例 。

axios 实例常用配置:

baseURL 请求的域名,基本地址,类型:String
timeout 请求超时时长,单位ms,类型:Number
url     请求路径,  类型:String
method  请求方法,  类型:String
headers 设置请求头,类型:Object
params  请求参数,将参数拼接在URL上,类型:Object
data    请求参数,将参数放到请求体中,类型:Object

4.2、axios 全局配置

示例代码 :

// 4.2、axios全局配置
// 配置全局的超时时长
this.$axios.defaults.timeout = 2000;
// 配置全局的基本 URL
this.$axios.defaults.baseURL = 'http://localhost:8080';

4.3、axios 实例配置

示例代码 :

// 4.3、axios实例配置
let instance = this.$axios.create();
instance.defaults.timeout = 3000;

4.4、axios 请求配置

示例代码 :

// 4.4、axios 请求配置
this.$axios.get('/goods.json', {
  timeout: 3000
}).then()

以上配置的优先级为:请求配置 > 实例配置 > 全局配置


5、拦截器

拦截器:在请求或响应被处理前拦截它们

5.1、请求拦截器

示例代码 :

// 5.1、请求拦截器
this.$axios.interceptors.request.use(
  config => { // 发生请求前的处理
    return config
  }, err => { // 请求错误处理
    return Promise.reject(err);
  }) // 或者用 axios 实例创建拦截器
let instance = this.$axios.create();
instance.interceptors.request.use(config => {
  return config
})

5.2、响应拦截器

示例代码 :

// 5.2、响应拦截器
this.$axios.interceptors.response.use(
  res => { // 请求成功对响应数据做处理				
    return res // 该返回对象会传到请求方法的响应对象中			
  }, err => { // 响应错误处理				
    return Promise.reject(err);
  })

5.3、取消拦截

示例代码 :

// 5.3、取消拦截
let instance = this.$axios.interceptors.request.use(config => {
  config.headers = {
    token: ''
  }
  return config
})
// 取消请求拦截:this.$axios.interceptors.request.eject(instance);
// 取消响应拦截:this.$axios.interceptors.response.eject(instance);

6、错误处理

示例代码 :

// 6、错误处理
this.$axios.get('/url').then(res = {}).catch(
  err => {
//请求拦截器和响应拦截器抛出错误时,返回的 err 对象会传给当前函数的 err 对象				
    console.log(err);
  })

7、取消请求

主要用于取消正在进行的 http 请求 。

示例代码 :

// 7、取消请求
let source = this.$axios.CancelToken.source();
this.$axios.get('/goods.json', {
    // 只有配置 cancelToken: source 才可取消请求		
    cancelToken: source
  })
  .then(res => {
    console.log(res)
  })
  .catch(err => {
    // 取消请求后会执行该方法				
    console.log(err)
  })
//取消请求,参数可选,该参数信息会发送到请求的 catch 中
source.cancel('取消后的信息');

axios 封装代码(直接使用)

一、在组件中调用 封装在 http 文件中

import axios from 'axios'

//创建 axios 实例
const axiosObj = axios.create({
  baseURL: 'http://api.web1024.cn',
  timeout: 8000,
  params: {
    key: 'gxn759'
  }
})

/**
 * 用于发送请求的通用方法
 * @param {*} options 配置信息,method请求方法,params参数,path路由
 * @returns 
 */
async function http({
  method = 'get',
  params,
  path
}) {

  let result

  if (method === 'get' || method === 'delete') {
    await axiosObj[method](path, {
      params
    }).then(res => {
      result = res.data
    }, err => {
      result = err
    })
  } else if (method === 'post' || method === 'put' || method === 'patch') {
    await axiosObj[method](path, params).then(res => {
      result = res.data
    }, err => {
      result = err
    })
  }

  return result
}

export default http

二、需要挂载到 Vue 的时候 直接导入文件 Vue.use(xxx) 就可以,Vuex 想用的时候, 直接导入以后直接使用就行
index.js

import axios from "axios";
import Auth from '@/assrts/js/auth/js'
import router from "@router/index.js";

// 基础配置
export const http = axios.create({
  baseURL: "http://api.web1024.cn",
  timeout: 8000,
  params: {
    key: "gxn759",
  },
});

// 请求拦截器
http.interceptors.request.use(
  function (config) {
    if (config.url != "/login") {
      config.headers["Authorization"] = Auth.getToken();
    }
    return config;
  },
  function (err) {
    return Promise.reject(err);
  }
);

// 响应拦截器
http.interceptors.response.use(
  function (response) {
    const {
      meta
    } = response.data;
    if (meta.status === 403) {
      window.alert("您没有权限执行该操作");
    } else if (meta.status === 401) {
      window.alert("你的登录信息有误,请重新登录!");
      router.push({
        name: "login",
        query: {
          redirect: window.location.hash,
        },
      });
    }
    return response;
  },
  function (err) {
    return Promise.reject(err);
  }
);

//最后
const httpPlugin = {};

httpPlugin.install = function (Vue) {
  Vue.prototype.$http = http;
};

Vue中的组件

组件(Component)是 Vue.js 最强大的功能之一。它可以扩展 HTML 元素,封装可重用的代码。

注册一个全局组件语法格式如下:

Vue.component(tagName, options)

tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:

<tagName></tagName>

全局组件

所有实例都能用全局组件。

<div id="app">
  <runoob></runoob>
</div>

<script>
  // 注册
  Vue.component('runoob', {
    template: '<h1>自定义组件!</h1>'
  })
  // 创建根实例
  new Vue({
    el: '#app'
  })
</script>

局部组件

可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:

<div id="app">
  <runoob></runoob>
</div>

<script>
  var Child = {
    template: '<h1>自定义组件!</h1>'
  }
  // 创建根实例
  new Vue({
    el: '#app',
    components: {
      // <runoob> 将只在父模板可用
      'runoob': Child
    }
  })
</script>

组件之间的数据传递

组件之间一般都是在总的大组件(vue实例)中请求拿到数据,再去传递到小组件,以此达到复用的目的。

Props(父→子)

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return {
          message: 'hello'
        }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

自定义事件(子→父)

父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!

我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口( Events interface ),即:

  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件

另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。

<div id="app">
  <div id="counter-event-example">
    <p>{{ total }}</p>
    <button-counter v-on:increment="incrementTotal"></button-counter>
    <button-counter v-on:increment="incrementTotal"></button-counter>
  </div>
</div>

<script>
  Vue.component('button-counter', {
    template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
    data: function () {
      return {
        counter: 0
      }
    },
    methods: {
      incrementHandler: function () {
        this.counter += 1
        this.$emit('increment')
      }
    },
  })
  new Vue({
    el: '#counter-event-example',
    data: {
      total: 0
    },
    methods: {
      incrementTotal: function () {
        this.total += 1
      }
    }
  })
</script>

如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:

<my-component v-on:click.native="doTheThing"></my-component>

其中,data 必须是一个 函数

这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝,如果 data 是一个对象则会影响到其他实例,如下所示:

<div id="components-demo3" class="demo">
  <button-counter2></button-counter2>
  <button-counter2></button-counter2>
  <button-counter2></button-counter2>
</div>

<script>
  var buttonCounter2Data = {
    count: 0
  }
  Vue.component('button-counter2', {
    /*
    data: function () {
        // data 选项是一个函数,组件不相互影响
        return {
            count: 0
        }
    },
    */
    data: function () {
      // data 选项是一个对象,会影响到其他实例
      return buttonCounter2Data
    },
    template: '<button v-on:click="count++">点击了 {{ count }} 次。</button>'
  })
  new Vue({
    el: '#components-demo3'
  })
</script>

自定义组件的 v-model

组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。

<input v-model="parentData">

以下实例自定义组件 runoob-input,父组件的 num 的初始值是 100,更改子组件的值能实时更新父组件的 num:

<div id="app">
  <runoob-input v-model="num"></runoob-input>
  <p>输入的数字为:{{num}}</p>
</div>
<script>
  Vue.component('runoob-input', {
    template: `
<p>   <!-- 包含了名为 input 的事件 -->
  <input
    ref="input"
    :value="value" 
    @input="$emit('input', $event.target.value)"
  >
</p>
`,
    props: ['value'], // 名为 value 的 prop
  })

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

由于 v-model 默认传的是 value,不是 checked,所以对于复选框或者单选框的组件时,我们需要使用 model 选项,model 选项可以指定当前的事件类型和传入的 props

<div id="app">
  <base-checkbox v-model="lovingVue"></base-checkbox>
  <div v-show="lovingVue">
    如果选择框打勾我就会显示。
  </div>
</div>
<script>
  // 注册
  Vue.component('base-checkbox', {
    model: {
      prop: 'checked',
      event: 'change' // onchange 事件
    },
    props: {
      checked: Boolean
    },
    template: `
  <input
    type="checkbox"
    v-bind:checked="checked"
    v-on:change="$emit('change', $event.target.checked)"
  >
`
  })
  // 创建根实例
  new Vue({
    el: '#app',
    data: {
      lovingVue: true
    }
  })
</script>

实例中 lovingVue 的值会传给 checked 的 prop,同时当 <base-checkbox> 触发 change 事件时, lovingVue 的值也会更新。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值