Vue基础知识精简总结

Vue

基础

渐进式 JS 框架

MVC

M - Model 数据层(数据库)
V - View 视图层(页面、ejs)
C - Controler 控制层(路由)

MVVM

M - Model 数据层(data、computed…)
V - View 视图层(模板页面)
VM - ViewModel 视图模型层(vm 实例对象)

  • 数据能由 ViewModel 操作渲染到视图层上(当数据将来发生修改,自动重新渲染到视图层上-响应式)
  • 页面数据发生变化,能由 ViewModel 操作来修改数据层的数据
  • 数据 M --> V 也能 V --> M, 叫做双向数据绑定

new Vue(config)

new Vue({ el: '#app', data: {}, methods: {}, computed: {}, watch: {} })

模板语法

  • 双大括号表达式(插值语法)

    • 语法:{{JS表达式}}
    • 作用:用来渲染 JS 动态数据
    • 注意:只能用于标签内,不能作为标签属性

指令语法

  • 语法: v-xxx:propName=“JS 表达式” / v-xxx=“JS 表达式”
  • 作为标签属性使用
  • v-model
    • 用来双向数据绑定,常用于表单项
    • v-model="msg"
  • v-bind
    • 用来单向数据绑定(强制绑定数据)
    • v-bind:value="msg"
    • 简写 :value="msg"
  • v-on
    • 用来绑定事件
    • v-on:click="handleClick"
    • 简写 @click="handleClick"
  • v-if / v-else / v-else-if 条件渲染
    • 根据表达式结果选择渲染哪个元素,切换显示)
  • v-show 条件渲染
    • 区别
      • v-if 隐藏时,元素移除 DOM 树
      • v-show 隐藏时,通过 display: none 控制隐藏
      • 所以,如果元素频繁切换显示、隐藏,用 v-show 较好(因为它不会移除 DOM 树)
  • v-for 列表渲染
    • v-for="(item, index) in xxx" :key=“item.id”
  • v-text
    • 用于显示元素 textContent、innerText
  • v-html
    • 用于显示元素 innerHTML
  • v-cloak
    • 用于防止闪现(从插值语法变成真正数据),配置 [v-cloak]{ display: none; }
  • v-pre
    • 显示最原始的内容,不会被 Vue 解析
  • v-once
    • 只被 Vue 解析一次(只渲染一次)

自定义指令

  • 自定义局部指令
{
  directives: {
    'upper-text': function (el, binding) {
      el.textContent = binding.value.toUpperCase();
    }
  }
}
  • 自定义全局指令
Vue.directive("upper-text", function (el, binding) {
  el.textContent = binding.value.toUpperCase();
});

计算属性

  • computed 计算属性
    • 只读计算属性
    computed: { fullName() { return xxx; } }
    
    • 可读可写计算属性
    computed: { fullName: { get() {}, set(newVal) {} } }
    
    • 通常情况下,计算属性内部会使用 data 数据。一旦内部使用的 data 数据发生变化,计算属性就会重新计算结果。如果 data 数据没有变化,就不会重新计算,使用上一次的缓存结果(有缓存)。

监视属性

  • watch
      watch: { firstName(newVal, oldVal) {  } }
    
    • 监视一个已存在的 data 属性,一旦 data 属性发生变化,就会调用相应的函数处理

样式处理

  • class

    • <p class="red">xxx</p>
    • <p :class="red">xxx</p>
    • <p :class="{red: isRed}">xxx</p>
    • <p :class="[red, 'green']">xxx</p>
  • style

    • <p style="font-size: 16px;">xxx</p>
    • <p :style="{fontSize: '16px'}">xxx</p>
  • 如果样式是动态(可变的)用 style,如果静态写死就用 class

事件处理

  • v-on:eventName=“handleClick”

    • 回调函数的参数:event
  • v-on:eventName=“handleClick()”

    • 回调函数的参数:无
  • v-on:eventName=“handleClick(xxx)”

    • 回调函数的参数:xxx
  • v-on:eventName=“handleClick(xxx, $event)”

    • 回调函数的参数:xxx, event
  • v-on:eventName=“orderType = 1”

    • 不需要设置回调函数, orderType = 1 就是要执行的语句
    • 当函数语句只有一条时,可以使用
  • 事件修饰符

    • @click.prevent.stop=“xxx”
    • .prevent 禁止事件默认行为
    • .stop 阻止事件冒泡
  • 按键修饰符

    • @keyup.13=“xxx”
    • @keyup.enter=“xxx”

生命周期函数

  • 组件从创建到销毁过程中自动触发的函数

  • 初始化

    • beforeCreate 在数据代理之前触发,所以不能通过 this 访问 data、methods 等数据
    • created 在数据代理之后
    • beforeMount
    • mounted 发送请求、设置定时器、绑定自定义事件等一次性任务
  • 更新

    • beforeUpdate
    • updated
  • 卸载

    • beforeDestroy 清除定时器、解绑事件等收尾工作(防止内存泄漏)
    • destroyed

过渡和动画

<transition name="xxx"><p v-show="xxx">xxx</p></transition>

  • 默认样式:
    • 隐藏到显示 v-enter/v-enter-active/v-enter-to
    • 显示到隐藏 v-leave/v-leave-active/v-leave-to
  • 加上 name 属性:xxx-enter/xxx-enter-active/xxx-enter-to

过滤器

  • 用来格式化数据(时间)

  • 局部过滤器

// 定义过滤器
{
  filters: {
    formatDate(value, str) {
      return dayjs(value).format(str);
    }
  }
}
// 使用过滤器
{{time | formatDate('YYYY-MM-DD HH:mm:ss')}}
  • 全局过滤器
// 定义过滤器
Vue.filter('formatDate', function(value, str) {
    return dayjs(value).format(str);
  })
}
// 使用过滤器
{{time | formatDate('YYYY-MM-DD HH:mm:ss')}}

ref

  • 用来获取 DOM 元素或者组件实例对象
// 设置ref
<input ref="name" />;
// 获取ref的值
this.$refs.name;

插件

  • 扩展 Vue 的功能
// 定义插件
// 方式一
function MyPlugin(Vue) {}
// 方式二
const MyPlugin = {
  install: function (Vue) {},
};

// 使用插件
Vue.use(MyPlugin);

key

  • key 有什么用?

    • 能让相同层级节点更新时性能更好
  • key 的值是什么?

    • 能用 id 用 id
    • 如果没有 id,只有往数组后面添加、删除,或者数据如果不变可以用 index

响应式

  • 什么是响应式数据?

    • 更新了数据,数据会变化,同时页面也会变化
  • 哪些数据是响应式数据?

    • data 中定义的数据
    • 注意:如果给 data 数据后面新添加属性,这些属性不是响应式
      • 如果想变成响应式数据,需要使用 this.$set() / Vue.set()

组件

// 定义组件
const Component = Vue.extend(组件配置对象);

// 注册局部组件
{
  components: {
    Component: Component,
    Component: 组件的配置对象,
  }
}

// 注册全局组件
Vue.component(组件名称, Component);
Vue.component(组件名称, 组件的配置对象);

脚手架

  • 安装包

    • npm i @vue/cli -g
  • 创建脚手架

    • vue create xxx
  • 启动开发环境

    • npm run serve
  • 启动生产环境

    • npm run build

render方法

import Vue from "vue"; --> vun.runtime.esm.js
vun.runtime.esm.js 只包含运行时版本(不具备编译模板能力)
通过render方法,就能具备编译模板能力

new Vue({
  render: h => h(App)
}).$mount("#app");

组件间通讯

data为什么要是函数?

data有两种写法:1. 对象 2. 函数
在普通页面中,两种写法都行
但是在组件中,必须使用函数

如果在组件中,data使用对象,复用组件时这多个组件会共享同一份data数据
如果在组件中,data使用函数,复用组件时这多个组件会调用函数得到一份新data数据,每个组件的data数据都会不一样,所以不会互相影响

1.props(父子组件)

当使用props传数据的时候,如果组件声明接受了,就可以直接通过this使用
如果组件没有声明接受,属性会在this.$attrs上,可以通过$attrs访问

  • 适用场景:父子组件

  • 父传子:将数据通过 props 直接传递

// 父组件传递数据
<Child :name="name" />
// 子组件声明接受props
{
  props: ['name'],
  props: {name: String},
  props: {name: { type: String, required: true, default: xxx, validator() {} }},
}
// 子组件使用
this.xxx
// 如果属性没有通过props声明接受,那么可以通过$attrs来使用
this.$attrs.xxx
  • 子传父
    • 父组件定义更新数据的方法,以 props 方式传递给子组件,子组件声明接受调用函数,传递数据给父组件
    • 子组件调用使用

2.自定义事件(子向父)

作用:用来子组件向父组件通信
给哪个组件绑定自定义事件,就只有那个组件可以触发(使用)

  • 适用场景:子传父
方式一
 @add="add"
    绑定自定义事件
    事件名:add
    事件回调函数:add
// 绑定自定义事件
  <Child @add="add" />
// 触发事件
  this.$listeners.add();
  this.$emit('add')
方式二
  ref 如果设置给普通DOM元素,那么获取到的就是这个真实DOM元素
    如果设置给组件,那么获取带的就是组件实例对象
// 绑定自定义事件
  <Child ref="child" />
  
  mounted() {
    this.$refs.child.$on('add', this.add)
  }

// 触发事件
  this.$emit('add')
  所有组件实例对象都具备以下方法:
    $on(eventName, listener)     绑定自定义事件(持久)
    $once(eventName, listener)   绑定自定义事件(一次性)
    $off(eventName, listener)    解绑事件
    $emit(eventName, data)       触发自定义事件

3.全局事件总线(任意组件)

在这里插入图片描述
在这里插入图片描述

  • 适用场景:任意组件

  • 原理:

    • 本质上就是自定义事件
    • 给 Vue 的原型添加一个可以绑定事件的对象(Vue 的实例 vm、组件的实例 this)
    • 使用 Vue 的实例 vm 在 main.js 文件中最方便
  • 使用方式有两种:

  Vue.prototype.$bus = new Vue()
  beforeCreate() { Vue.prototype.$bus = this }
  • 所有组件实例对象都能通过原型链的方式访问到 $bus 这个对象,所以就能通过它绑定事件或者触发事件
// 绑定事件(接受数据):
this.$bus.$on(eventName, listener)

// 触发事件(发送数据):
this.$bus.$emit(eventName, data)

4.PubSub消息发布订阅(任意组件)

  • 使用场景:任意组件
  • 发布(发送数据):PubSub.publish(msg, data)
  • 订阅(接受数据): PubSub.subscribe(msg, listener)

5.插槽(父给子传递带数据标签)

  • 使用场景:父给子传递带数据的标签
默认插槽

组件写成双标签,里面放入标签数据,那么这个标签数据就会以插槽的方式传递给子组件

// 父组件给子组件传递带数据的标签
<AChild>
  <p>hello vue000</p>
  <p>hello vue11</p>
  <p>{{msg}}</p>
</AChild>
// 子组件使用
// 使用父组件以插槽方式传递的标签数据
<slot></slot>
具名、命名插槽

具名、命名插槽: 给每一个插槽取一个名字

 // 具名、命名插槽: 给每一个插槽取一个名字
 <BChild>
   // 旧语法:slot="名称"
   <template slot="header">
     <header>头部...{{ title }}</header>
   </template>

   // 新语法:v-slot:名称 
   <template v-slot:main>
     <main>内容区...</main>
   </template>

   // 新语法可以简写:#名称 
   <template #footer>
     <footer>底部...</footer>
   </template>
 </BChild>
  • 子组件使用
<template>
  <div>
    // 显示头部 
    // 通过name属性来决定使用哪个具名插槽 
    <slot name="header"></slot>
    <p>---------</p>
    // 显示内容区 
    <slot name="main"></slot>

    <p>---------</p>
    // 显示底部 
    <slot name="footer"></slot>
  </div>
</template>
作用域插槽
  • 父组件
 <CChild>
   // 父组件插槽可以接受子组件通过slot传递的props数据
   <template #list="slotProps">
   <template v-slot:list="slotProps">

   // { person } -> 就是对数据进行解构赋值
   <template #list="{ person }">

   <template #list="{ person: { name, age } }">
     <ul>
       <li>姓名:{{ name }}</li>
       <li>年龄:{{ age }}</li>
     </ul>
   </template>
 </CChild>
  • 子组件
<template>
  <div>
    // 以标签属性(props)方式传递person数据 
    <slot name="list" :person="person"></slot>
  </div>
</template>

<script>
export default {
  name: "CChild",
  data() {
    return {
      person: {
        name: "jack",
        age: 18,
      },
    };
  },
};
</script>

跨域

什么是跨域?

违背了同源策略

什么是同源策略

协议名、域名(ip 地址)、端口号三者必须完全一致

什么请求会有跨域问题?

只有位于客户端的 ajax 请求才可能出现跨域问题,
其他普通的 http 请求是不存在跨域问题的(script、服务器和服务器之间。。。)

解决跨域方式:

jsonp

  • 原理:利用 script 标签天然可以跨域的特性进行跨域
  • 步骤:
    • 创建 script 标签
    • 创建全局回调函数
    • 设置 script 的 src 属性,往往会添加一个 callback 请求参数
    • 将 script 标签添加到 body 中生效

cors

  • 原理:http 协议规定,指定响应头可以资源进行跨域访问
  • access-control-allow-origin 允许那些地址可以跨域
  • access-control-allow-headers 允许哪些请求头可以跨域
  • access-control-allow-methods 允许哪些请求方式可以跨域
  • access-control-max-age 预检请求缓存多久
    • 发送请求的时候,会先发送一个 options 请求,这个请求就叫预检请求
    • 默认请求下,每个请求之前会发,max-age 可以缓存预检请求结果,在缓存期间内,预检就不会再发了

服务器代理模式(proxy)

原理:
- 正常情况下,客户端直接访问目标服务器,会存在跨域问题
- 在客户端和目标服务器,设置一个代理服务器。
- 客户端先将请求发送给代理服务器,客户端和代理服务器之间没有跨域问题
  - 客户端和代理服务器运行的是同一个服务器
  - 代理服务器设置类似于 cors 方法解决了跨域
- 代理服务器接收到请求就会将请求转发到目标服务器上,服务器和服务器之间不存在跨域问题,所以请求 ok
- 目标服务器将响应返回给代理服务器,代理服务器再讲响应返回给客户端
正向代理
- 代理客户端,替客户端去转发请求(隐藏真正客户端)
- 例子:开发中 proxy,xxUtil
- 配置:
  - React 脚手架项目中:在 package.json 中配置 proxy
  - Vue 脚手架项目中:在项目根目录创建一个配置文件 vue.config.js,在其中
module.exports = {
  devServer: {
    proxy: {
      "/api": {
        target: "http://localhost:3000",
        pathRewrite: { "^/api": "" },
      },
    },
  },
};
反向代理
- 代理服务器,替服务器先接受请求,然后再将请求分配给某个服务器(隐藏真正的服务器)
- 例子:nginx
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值