Vue寒假学习笔记

1-14day

1.全局注册

html代码:

<div id="example">
  <my-component></my-component>
</div>

JS代码:

// 注册
Vue.component('my-component', {
  template: '<div>A custom component!</div>'
})
var vm = new Vue({
  el: '#example',
  data: {
       
  } 
})

渲染结果为:

<div id="example">
  <div>A custom component!</div>
</div>

或者另外一种注册方式,通过 全局API:Vue.extend()
代码如下:

// 注册
var MyComponent = Vue.extend({
  template: '<div>A custom component!</div>'
});

// 注册
Vue.component('my-component', MyComponent);
var vm = new Vue({
  el: '#example',
  data: {
       
  }
})

[复制代码](javascript:void(0)😉

Vue.extend()使用说明

下面说明下Vue.extend( options )的使用。
参数:{Object} options
用法:使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象
data 选项是特例,需要注意 - 在 Vue.extend()中它必须是函数

<div id="mount-point"></div>

[复制代码](javascript:void(0)😉

// 创建构造器
var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
  }
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')

Vue 的 m o u n t ( ) 为 手 动 挂 载 , 在 项 目 中 可 用 于 延 时 挂 载 ( 例 如 在 挂 载 之 前 要 进 行 一 些 其 他 操 作 、 判 断 等 ) , 之 后 要 手 动 挂 载 上 。 n e w V u e 时 , e l 和 mount()为手动挂载,在项目中可用于延时挂载(例如在挂载之前要进行一些其他操作、判断等),之后要手动挂载上。new Vue时,el和 mount()newVueelmount并没有本质上的不同。

结果如下:

<p>Walter White aka Heisenberg</p>

这个步骤就是生命周期的beforemount,mount

自定义事件

我们知道,父组件使用 prop 传递数据给子组件。但子组件怎么跟父组件通信呢?这个时候 Vue 的自定义事件系统就派得上用场了。

使用 v-on 绑定自定义事件

每个 Vue 实例都实现了事件接口,即:

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

Vue 的事件系统与浏览器的 EventTarget API 有所不同。尽管它们的运行起来类似,但是 $on$emit 并不是addEventListenerdispatchEvent 的别名。

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

不能用 $on 侦听子组件释放的事件,而必须在模板里直接用 v-on 绑定,参见下面的例子。

<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>

[复制代码](javascript:void(0)😉

Vue.component('button-counter', {
  template: '<button v-on:click="incrementCounter">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    incrementCounter: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})

new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})

组件化开发

我们在mui-ui组件网站使用的组件,也是开发人员开发的组件,例如:mui-button组件就是一个vue组件,我们在这里就可以看见了

就是按需导入:(选择整个组件文件,并选择导入Button)

import { Button } from 'mint-ui';
Vue.use(Button)

全局导入:

import Mint from 'mint-ui'
import 'mint-ui/lib/style.css'
Vue.use(Mint)

Vue.use()可以和vue一起加载,随时使用

import axios from 'axios'
const Axios = {
  install (Vue) {
    const result = axios.create({ baseURL: 'http://tpadmin.test/api/' })
    Vue.prototype.$http = result
  }
}
export default Axios

install是必须的,换成test()就会不识别

把axios注册成原型对象,使用的时候很方便

视频:https://www.bilibili.com/video/BV1FS4y1d7q9?from=search&seid=918740444835597733&spm_id_from=333.337.0.0

文档:https://blog.csdn.net/github_37516320/article/details/78321391

axios注册

  1. created(){}方法里面尽量放methods的方法,

1-15日

api文档

position:relative;是相对定位,是相对于自己的定位,需要使用left top bottom right

position:absole是绝对定位,上级元素有绝对定位,相对的定位,就以上一个定位方式为标准

  1. img的width,height大小,可以压缩图片,

  2. 上一级div对图片img限制的用:overflow:hidden;进行裁剪图片

  3. api文档实例的 登录接口

    • 请求路径:login //这里使用.post(login)
    • 请求方法:post
    • 请求参数
      .post(login,this.login),所以post()的第一个参数是请求地址,第二个是传递参数(一整个参数传过去)
    • 但是传递的参数有要求,必须要使用下面的字段,否则无法识别
    参数名参数说明备注
    username用户名
    password密码
    • 响应参数
    参数名参数说明备注
    code状态码1登录成功 0登录失败
    msg提示信息
    url
    data登录人员信息
    • 响应数据
      下面就是result.data请求之后的数据,就使用需要使用判断code的值是多少,然后获取失败的话就用this.$toast(result.data.msg)弹出消息
    {
      "code": 1,
      "msg": "登录成功",
      "data": {
        "session_id": "akemvcqn21dscu5bupg5sn5p7t", //注意,登录时将会额外得到一个session_id的数据
        "id": 1,
        "username": "test"
      },
      "url": "http://localhost:10086/",
      "wait": 3
    }
    

    vuex

    $store.getters[‘user/isLogin’]

    $store.state.user.username

    this.$store.commit(‘user/setUser’, result.data.data)

1-16日

1.session

Session:记录一系列状态,例如:这样服务器才知道你在下一个页面用不用重新登录,服务器才知道你当前的状态,更好的推送东西,这是与cookies的区别之一

Session与cookie功能效果相同。Session与Cookie的区别在于Session是记录在服务端的,而Cookie是记录在客户端的。

解释session:当访问服务器否个网页的时候,会在服务器端的内存里开辟一块内存,这块内存就叫做session,而这个内存是跟浏览器关联在一起的。这个浏览器指的是浏览器窗口,或者是浏览器的子窗口,意思就是,只允许当前这个session对应的浏览器访问,就算是在同一个机器上新启的浏览器也是无法访问的。而另外一个浏览器也需要记录session的话,就会再启一个属于自己的session

原理:***HTTP协议是非连接性的,取完当前浏览器的内容,然后关闭浏览器后,链接就断开了,而没有任何机制去记录取出后的信息。***而当需要访问同一个网站的另外一个页面时(就好比如在第一个页面选择购买的商品后,跳转到第二个页面去进行付款)这个时候取出来的信息,就读不出来了。所以必须要有一种机制让页面知道原理页面的session内容。

问题:如何知道浏览器和这个服务器中的session是一一对应的呢?又如何保证不会去访问其它的session呢?

原理解答:**就是当访问一个页面的时候给浏览器创建一个独一无二的号码,也给同时创建的session赋予同样的号码。**这样就可以在打开同一个网站的第二个页面时获取到第一个页面中session保留下来的对应信息(理解:当访问第二个页面时将号码同时传递到第二个页面。找到对应的session)。这个号码也叫sessionID,session的ID号码,session的独一无二号码。(就是发送过去session_id,把他放在请求头中发送给服务器)

2.登录验证

目的是为了:1.让服务器认识多个请求都是一个客户发出来的,在服务器的多个网页下保存状态.2.保存住客户的状态

Http协议是无状态的,同一个客户多次访问服务器,服务器无法识别同一个客户的关联请求,也无法保存客户的状态。要解决这个问题,服务器需要获取到客户的身份,客户需要在每次发起Http请求的时候携带相应的身份信息,服务端获取到这个身份信息以后再返回相应的资源。我们在使用Web系统时,提供用户名和密码的过程就是向客户端提供身份认证信息的过程,那么在做接口测试的时候如何模拟用户登录过程,在每一次的接口请求中携带客户的身份信息呢?

在解决这个问题以前我们首先要了解常用的Http认证授权技术:
基于表单的认证(Cookie & Session):基于表单的认证并不是在HTTP协议中定义的,而是服务器自己实现的认证方式,安全程度取决于实现程度。一般用Cookie来管理Session会话,是最常用的认证方式之一。它的安全程度取决于服务器的实现程度,客户端在Cookie中携带认证信息,服务器解析并返回结果。

基于JWT(Json Web Token)的认证:App和服务端常用的认证方式,用户ID和密码传输到服务器上验证,服务器验证通过以后生成加密的JWT Token返回给客户端,客户端再发起请求时携带返回的Token进行认证。

Http Basic认证:最早的Http认证方式,用户ID和密码以分号连接,经过Base64编码后存储到Authorization字段,发送到服务端进行认证 ;用户ID/密码以明文形式暴露在网络上,安全性较差。

Http Digest认证:在HttpBasic的基础上,进行了一些安全性的改造,用户ID, 密码 , 服务器/客户端随机数,域,请求信息,经过MD5加密后存储到Authorization字段,发送到服务端进行认证;密码经过MD5加密,安全性比Basic略高。

其他认证方式(Oauth认证,单点登陆,HMAC认证):通过特定的加密字段和加密流程,对客户端和服务端的信息进行加密生成认证字段,放在Authorization或者是消息体里来实现客户信息的认证

除了上述四种,还有很多其他的认证方式,包括现在很流行的单点登录。但无论哪一种认证方式,Http都是无状态的,绕过登录的核心都是在Http请求中携带认证信息。这个认证信息我们可以通过和开发同学沟通签名加密的流程和字段,在客户端通过编码方式实现;也可以通过抓包工具抓取到相应的认证字段,然后通过Jmeter组件把字段添加到发起的Http请求当中。

3.区别:通过存储方式及类型区别

  1. 存储位置 : vuex存储在内存,而session则以文件的方式存储在本地;
  2. 应用场景 : vuex用于组件间的传值,而session则用于页面间的传值;
  3. 时效性 : vuex存储的值刷新时会丢失,而localstorage不会清除,除非手动删除;

4.接口文档设计技巧

登录接口

  • 请求路径:login
  • 请求方法:post
  • 请求参数
参数名参数说明备注
username用户名
password密码
  • 响应参数
参数名参数说明备注
code状态码1登录成功 0登录失败
msg提示信息
url
data登录人员信息
  • 响应数据
{
  "code": 1,
  "msg": "登录成功",
  "data": {
    "session_id": "akemvcqn21dscu5bupg5sn5p7t", //注意,登录时将会额外得到一个session_id的数据
    "id": 1,
    "username": "test"
  },
  "url": "http://localhost:10086/",
  "wait": 3
}

个人经验:

  1. 设置session_id是为了和浏览器沟通,
  2. id使用来在vuex判断是否登录了,然后给页面判断登录前和登录后的页面.
  3. username用户们用来显示用户名数据,也可以继续设置显示其他的

5. axios的拦截器(Interceptors)

axios 的拦截器:interceptors

如果我们想在请求之前做点什么,用拦截器再好不过了

拦截器一般做什么?

      1. 修改请求头的一些配置项

         2. 给请求的过程添加一些请求的图标

                   3. 给请求添加参数

​ 总之就是调整请求头里面的数据

const res = Vue.prototype.$auth
    const result = axios.create({ baseURL: 'http://tpadmin.test/api/' })
    result.interceptors.request.use((config) => {
      config.headers.Authorization = res.getAuthorization()
      return config
    })
    Vue.prototype.$http = result

6.localStorage的使用

localStorage的方法是直接操作浏览器本地储存的数据

  1. localstorage.getItem()取的是key的名字
  2. localstorage.setItem(key:value)设置,默认是token,还有这个办法localStorage.removeItem(‘token’)
getAuthorization () {
    return localStorage.getItem('Authorization')
  },
  setAuthorization (Authorization) {
    localStorage.setItem('Authorization', Authorization)
  }

提交的请求可以先让他先加载一下,this.$indicator.open({‘text’:…})

image-20220118151532344

1-17day

1.display:flex

两个div块级元素在一起,

肯定是一个在上面,一个在下面布局.(flex可以控制左右,上下排序)

为了解决这种情况可以使用弹性盒子布局,这样就有一个在右边一个在左边

img

https://www.cnblogs.com/hellocd/p/10443237.html

  1. flex:1会根据剩下的宽度自动排行.

  2. flex-flow: row wrap;第一个是排列方式,第二个是换行

  3. .menu {
      display: flex;
      position: absolute;
      text-align: center;
      top: 40px;
      bottom: 50px;
      width: 100%;
      overflow: hidden;
     // 这个oberflow是为在左边可以一直显示菜单的   
      }
    

image-20220117131135587

  1. 这个是没有高度的,所以需要在下面的菜单要加position定位元素,不要遮住

  2. li加了高度后,可以在里面的文字加行高

  3. flex: 1;

    // 剩下的宽度都是由这个分配

4.初始化的方法开头用 _initxxxxx()方法

data(){
	return{
	imgList:[]
	}
},
wacth:{
	// wacth里面的数据是函数形式
	imgList(){
		this.$nextTick(()=>{
		
		})
	}	
}

2.滚动组件

5.1.1 better-scroll滚动组件

为了在Vue中实现左右菜单联动的滚动效果,需要借助better-scroll滚动组件来完成。

在项目中使用如下命令安装better-scroll插件。

npm install better-scroll@1.15.2 --save

安装后,打开src\pages\Category.vue文件,导入better-scroll插件。

<script>
    import BScroll from 'better-scroll'
</script>

better-scroll插件需要操作DOM,因此要确保在menus数据加载完成后,并且已经在页面中显示出来以后,再来初始化better-scroll。所以,可以利用watch监听menu的数据变动,一旦发生变动,则页面也会发生变化。

为了确保DOM渲染完成后,再初始化better-scroll,在这里需要使用this.$nextTick异步函数,示例代码如下。

watch: {

 menus () {

  // $nextTick用来在下次DOM更新循环结束之后执行延迟回调

  this.$nextTick(() => {

   this._initBScroll()   // 初始化better-scroll

  })

 }

},

在methods中编写_initBScroll()方法,实现better-scroll的初始化。

methods: {

 ……(原有代码)

 // 初始化better-scroll

 _initBScroll() {

  this.leftBscroll = new BScroll('.menu-left', {

   click: true,

   mouseWheel: true

  })

  this.rightBscroll = new BScroll('.menu-right', {

   click: true,

   mouseWheel: true

  })

 }

}

上述代码中,使用new BScroll()创建一个实例,第1个参数表示对应的元素,第2个参数表示选项。在选项中,click表示是否允许单击,mouseWheel表示可以用鼠标滚动进行滚动。

6.一个页面很长可以用滚动条的值去控制

1-18day

1. 路由

image-20220118133814114

image-20220118150000682

image-20220118150119858

image-20220118150218941

固定路由缺点:路由规则的复用性差。动态路由可以传值

image-20220118150330557

props传的是路由url的参数

image-20220118150500803

image-20220118150706131

image-20220118150801685

image-20220118151010047

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bI3qAskR-1645598896042)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220118151019115.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ZKkifxo-1645598896044)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220118151200685.png)]

router.beforeEach((to,form,next)=>{})

注意:
① 在守卫方法中如果不声明 next 形参,则默认允许用户访问每一个路由!
② 在守卫方法中如果声明了 next 形参,则必须调用 next() 函数,否则不允许用户访问任何一个路由!

image-20220118151305814

image-20220118151355164

image-20220118151511810

2.导航栏

image-20220118151923250

右边显示的这个位置,可以放组件,也可以一整个数据都放下去之后根据每个数据块的高度调整

image-20220118152118411

3.细节点

 <router-link :to="'/GoodList/' +menu.id" class="cate-item-wrapper"> </router-link>

在这里的 "’/GoodList/’+menu.id"是在拼接url的.

index.js

{
    path: '/GoodList/:category_id',
    component: Good,
    props: true,
    meta: { title: '商品列表' }
  }

之后就接收到:category_id这里了,

props: ['category_id'],

个人经验认为:路由的不同是根据参数个数判断的,所以会把menu.id赋值给category_id然后传值给组价.组件的props名称与路由参数需要保持一致,不然不会识别

1-19day

1.数据代理

let number=185
    let person = {
      name:'lqc',
      sex:'男',
    }
    
 Object.defineProperty(person,"height", {
      // value:185,
      // 可枚举的意思
      // enumerable:true,
      // // 可以被修改的意思
      // writable:true,
      // // 可以被删除的意思
      // configurable:true,
      get:function(){
        return number
      },
      set(height){
        number=height
      }
    })
data(){
	return {
	name:'java'
	}
}

data里面的数据是通过defineProperty()数据代理上去的

image-20220119123923502

 let vm = new Vue({
      el: "#one",
      data: {
        name:'java'
      },
      methods: {},
    })

data是vm的一个属性,但是vm.data是找不到的.data会变成vm._data,所以vm._data就是data

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZhRZmsF-1645598896052)(D:\Desktop\image-20220119125642423.png)]

第一个:白箭头是到浏览器的运行过后的变化;两次都是数据代理,get方法可以让其他方法获取自己,set是用来修改自己的

小知识:

image-20220119130122005

$开头的是给我们程序员准备的,_开头的是给vue底层使用的

image-20220119145749535

2.深度监视

image-20220119203910608

3.vue传参的方式

 this.$http.get('goodslist', { params: { category_id: this.category_id } })

传参通过{ params : { category_id: this.category_id } }

Flex知识

Flex 布局语法教程

分类 编程技术

网页布局(layout)是CSS的一个重点应用。

img

布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。

img

2009年,W3C提出了一种新的方案—-Flex布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。

img

Flex布局将成为未来布局的首选方案。本文介绍Flex布局的语法。

一、Flex布局是什么?

Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。

任何一个容器都可以指定为Flex布局。

.box{
  display: flex;
}

行内元素也可以使用Flex布局。

.box{
  display: inline-flex;
}

Webkit内核的浏览器,必须加上-webkit前缀。

.box{
  display: -webkit-flex; /* Safari */
  display: flex;
}

注意,设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。

二、基本概念

采用Flex布局的元素,称为Flex容器(flex container),简称”容器”。它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称”项目”。

img

容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。

项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。

三、容器的属性

以下6个属性设置在容器上。

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

3.1 flex-direction属性

flex-direction属性决定主轴的方向(即项目的排列方向)。

.box {
  flex-direction: row | row-reverse | column | column-reverse;
}

img

它可能有4个值。

  • row(默认值):主轴为水平方向,起点在左端。
  • row-reverse:主轴为水平方向,起点在右端。
  • column:主轴为垂直方向,起点在上沿。
  • column-reverse:主轴为垂直方向,起点在下沿。

3.2 flex-wrap属性

默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap属性定义,如果一条轴线排不下,如何换行。

img

.box{
  flex-wrap: nowrap | wrap | wrap-reverse;
}

它可能取三个值。

(1)nowrap(默认):不换行。

img

(2)wrap:换行,第一行在上方。

img

(3)wrap-reverse:换行,第一行在下方。

img

3.3 flex-flow

flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。

.box {
  flex-flow: <flex-direction> <flex-wrap>;
}

3.4 justify-content属性

justify-content属性定义了项目在主轴上的对齐方式。

.box {
  justify-content: flex-start | flex-end | center | space-between | space-around;
}

img

它可能取5个值,具体对齐方式与轴的方向有关。下面假设主轴为从左到右。

  • flex-start(默认值):左对齐
  • flex-end:右对齐
  • center: 居中
  • space-between:两端对齐,项目之间的间隔都相等。
  • space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

3.5 align-items属性

align-items属性定义项目在交叉轴上如何对齐。

.box {
  align-items: flex-start | flex-end | center | baseline | stretch;
}

img

它可能取5个值。具体的对齐方式与交叉轴的方向有关,下面假设交叉轴从上到下。

  • flex-start:交叉轴的起点对齐。
  • flex-end:交叉轴的终点对齐。
  • center:交叉轴的中点对齐。
  • baseline: 项目的第一行文字的基线对齐。
  • stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。

3.6 align-content属性

align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

.box {
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}

img

该属性可能取6个值。

  • flex-start:与交叉轴的起点对齐。
  • flex-end:与交叉轴的终点对齐。
  • center:与交叉轴的中点对齐。
  • space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
  • space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
  • stretch(默认值):轴线占满整个交叉轴。

四、项目的属性

以下6个属性设置在项目上。

  • order
  • flex-grow
  • flex-shrink
  • flex-basis
  • flex
  • align-self

4.1 order属性

order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。

.item {
  order: <integer>;
}

img

4.2 flex-grow属性

flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

.item {
  flex-grow: <number>; /* default 0 */
}

img

如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

4.3 flex-shrink属性

flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

.item {
  flex-shrink: <number>; /* default 1 */
}

img

如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。

负值对该属性无效。

4.4 flex-basis属性

flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。

.item {
  flex-basis: <length> | auto; /* default auto */
}

它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。

4.5 flex属性

flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。

.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。

建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。

4.6 align-self属性

align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

img

该属性可能取6个值,除了auto,其他都与align-items属性完全一致。

1-20day

1. 在vue中拼接url的方式有很多

比如例子一:

 <router-link :to="{name:'GoodInfo',params:{id:item.id}}"></router-link>

这种方式必须要在路由文件之中设置name的值

 {
    path: '/GoodInfo/:id',
    name: 'GoodInfo',
    component: GoodInfo,
    props: true,
    meta: { title: '商品详情' }
  }

例子二:

<router-link :to="'/GoodList/' +menu2.id" class="cate-item-wrapper"></router-link>

直接拼接

还有发送的请求:

 this.$http.get('goodsinfo', { params: { id: this.id } })

商品的余量可以用来判断是否有货然后进行显示

  1. @change当输入框失焦的时候触发而且在elementUI中使用change时是这样的@visible-change(类似于:等你输入完成之后在启动事件)

    @input是输入框发生变化时触发,也就是说输入框一动就出触发了(一变化就启动事件)

2.进入购物车前需要商品的id,还有购买的数量

image-20220120175359539

1-21day

image-20220121082027316

some()

定义和用法

some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。

some() 方法会依次执行数组的每个元素:

如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
如果没有满足条件的元素,则返回false。

注意: some() 不会对空数组进行检测。

注意: some() 不会改变原始数组。

数组添加

array.push() 从尾添加

array.unshift() 从头添加

:key diff算法

  1. 相当于身份证号,写了之后不会在真实的DOM浏览器出现的,是vue底层在使用.
  2. 虚拟dom在内存之中,key是索引的话,image-20220121204006338

image-20220121205546605

不加key默认是加index

image-20220121204429209

会用虚拟dom的key看看里面的东西有没有变化,没有变化就使用真实Dom,有变化的话,看里面的新的变为新的dom,旧的继续复用

1-22day

localstorange的key改变的方式,就是相当于给对应的key重新赋值,就会把原来的值覆盖掉

在实现购物车功能的时候,由于每次刷新页面后需要将购物车中的商品保留下来(vuex刷新之后就没有了),所以需要保存购物车中的商品信息到localStorage中

​ setItem()方法接受name和item形参,在setItem()方法中,通过localStorage本地存储对象的setItem()方法实现本地数据存储功能,其中参数name表示名称**,JSON.stringify(item)表示转换为JSON字符串后的值。**getItem()方法接受name形参,在getItem()方法中,返回一个经过JSON.parse()转换后的JSON对象,其中localStorage.getItem()方法表示获取指定名称的值。

1-23day

更新

v-model=“getGoodsSelected[item.id]”

:checked=“getGoodsSelected[item.id]”

vuex传送的数据的例子:

<template>
  <div class="shopcar-container">
    <div class="goods-list">
      <div class="mui-card">
        <div class="mui-card-content" v-for="item in shopgoods" :key="item.id">
          <div class="mui-card-content-inner flex">
            <!-- 复选框 -->
            <div class="mui-input-row mui-checkbox mui-left">
              <label>&nbsp;</label>
              <input type="checkbox">
            </div>
            <!-- 中间商品图片 -->
            <img :src="item.image">
            <!-- 右侧部分 -->
            <div class="info">
              <h1>{{ item.name }}</h1>
              <p class="flex">
                <span class="price">¥{{ item.price }}</span>
                <numbox :initcount="getGoodsCount[item.id]" :max="item.num" :goodid="item.id"></numbox>
                <a href="#">删除</a>
              </p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { mapState, mapGetters } from 'vuex'
import numbox from '../components/numbox.vue'
export default {
  name: 'Shopcar',
  components: {
    numbox
  },
  data () {
    return {
      shopgoods: ''
    }
  },
  computed: {
    // 将他制作为computed的属性
    // car为制作名称
    ...mapState('shopcar', ['car']),
    ...mapGetters('shopcar', ['getGoodsCount'])
  },
  created () {
    this.getGoodList()
    console.log('....')
    console.log(this.getGoodsCount)
  },
  methods: {
    getGoodList () {
      console.log(this.car)
      const arr = []
      this.car.forEach(item => {
        arr.push(item.id)
      })
      this.$http.get('shopcart', { params: { ids: arr } }).then(res => {
        console.log(res.data)
        this.shopgoods = res.data.data
      })
    }
  }
}
</script>

<style lang="scss" scoped>
</style>

vue中把页面之间传输的数据,变为放在vuex之中,在页面之中可以利用…mapGetters(‘页面’,[‘方法’])把vuex中的State搬运过来成为计算属性,进行利用,对vuex的数据进行筛选的时候,会出现一整个vuex只需要一个数据的情况,这个时候就需要利用商品id进行查询了

修改vuex里面的数据,需要根据id先遍历,然后进行修改,然后提交到localrange()

input的监控有@change和@input

普通的有data加上watch

json特点

image-20220123153104921

1-24day

:disabled是废除功能的意思

:disabled=“item.num===0”

vuex存的是各个页面之间传递的信息,比如上一个购物页面要存多少件物品,到下个页面展示,还有勾选数量,还有商品id,可以拿来给axios发送请求,获得更多信息,进行补充完整.

splice()用于添加或者删除,(第一个是索引,第二个是删除的个数,第三个参数是添加的元素)

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2,0,"Lemon","Kiwi"); 

Snipaste_2022-01-24_20-13-42

94befff571ef4775b5602d195560bc97

  1. created与beforeMount之间就是找到模板,然后转化为虚拟dom

  2. beforeUpdate是数据是新的,页面是旧的;更新数据之后会更新虚拟Dom,进行对比之后更新真实Dom

  3. image-20220124205957356

    1-25day

    1.没有scoped的时候,看组件引入的顺序,决定css的值,因为没有scoped所有组件的css都是汇总到一起的,难免发生冲突;有scoped之后,在组件之内就这各css只能在组件内使用

    ​ less不可以下载,有时候需要考虑webpack的版本问题

    ​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J3CiWMSi-1645598896091)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220125124626671.png)]

数据代理

在这里,外面number改变了,里面person的number值不会发生改变,就比如vm._data的age值发生改变了,vm.age不会发生变化

image-20220125133226922

用Object.defineProperty(对象,key,value)当外面的number发生变化了,调用person的age也会发生变化,这样就形成了关联

image-20220125133149753

get的名字

image-20220125134117617

image-20220125145711264

vm.name用的是vm._data里面的name数据,修改vm.name也会使vm._data里面的数据发生变化

image-20220125145932338

Observer数据监视

image-20220125155656453

Vue.set()

image-20220125161644713

用普通的办法,sex是会添加上去,但是没有get() set(),这样他就不是响应式的了,后添加的数据是不添加响应式的,也不在vm里面

image-20220125162741628

vue.set()与vue.$set()是一样的

vm._data.student===vm.student是一样的

但是set()方法只能添加到data的对象(student)里面,是不可直接添加到data的

组件库选择

image-20220125164214198

vue.use()详情

image-20220125192131689

component.name是组件名字就是<名字>实例化的组件的名字,component是引入的组件

数组修改

数组的添加删除,pop() push() unshift(),shift(),splice(),sort(),reverse()

1-26day

js的阻塞特性?

v-clock特性

image-20220126012038091

v-pre

不编译所在节点

v-once

  1. v-once所在节点初次渲染之后,就被视为静态内容了.2.以后数据更新不会引起v-once的里面数据的更新

自定义指令

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="one">
    <h2 v-text="a"></h2>
    <h3 v-big="20"></h3>
    <input type="text" placeholder="123" autofocus>
    <button @click="a++">+</button>
  </div>
  <script src="./vue.js"></script>
  <script>
    let vm = new Vue({
      el: "#one",
      data: {
        a:1,
      },
      directives:{
        big:function(element,binding){
          // 指令就是放在dom节点里面后就是调用
          console.log("big");
        //  真实dom 
          console.log(element);
          console.log(binding);
          element.innerText=binding.value*10
        },
        focus(element,binding){
          element.focus()
        }
      },
      methods: {},
    })
  </script>
</body>

</html>

传统开发模式

image-20220126145058716

缺点:

1. js文件互相调用,要理清楚js之间的依赖关系,不然直接报错,较为繁琐,还有css要关注到底那个文件使用了

2.css修改了,其他html样式就无法使用了.还有就是同名就会覆盖错误

3. 模块化知识

​ 复用性差,复用起来麻烦

a.js中定义一个方法
function a(){
}
 
b.js中定义一个方法
function b(){
}
 
在a.js中访问b.js中方法
b();//就可以直接访问b方法

解决函数,命名冲突,出现了模块化

vue的scoped的优点就是很好的解决了冲突的问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R4POGUib-1645598896111)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220126150018512.png)]

image-20220126150002481

image-20220126150633898

image-20220126150457199

把页面的一整个js拆分成很多份就是模块化

export 和export default 的区别在于:export 可以导出多个命名模块,例如:

//demo1.js
export const str = 'hello world'

export function f(a){
    return a+1
}

对应的引入方式:

//demo2.js
import { str, f } from 'demo1'

export 导入的时候需要要记住变量名和函数名字,为了方便所以有了**,默认导出导入时候必须有花括号。**

export default 只能导出一个默认模块,这个模块可以匿名,例如:

//demo1.js
export default {
    a: 'hello',
    b: 'world'      
}

对应的引入方式:

//demo2.js
import obj from 'demo1'

引入的时候可以给这个模块取任意名字,例如 “obj”,且不需要用大括号括起来。

js的模块化进程

现在前端技术日新月异,对于同一个问题痛点,各个时段有各自的解决方案,这就带来了很大差异。今天我就打算梳理js模块化的历史进程,讲一讲这些方案要做什么,怎么做。

js模块化进程的起因

现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。当一个项目开发的越来越复杂的时候,你会遇到一些问题:命名冲突(变量和函数命名可能相同),文件依赖(引入外部的文件数目、顺序问题)等。

JavaScript发展的越来越快,超过了它产生时候的自我定位。这时候js模块化就出现了。

webpack

1.先用fs模块读取模块内容,之后用bebal处理依赖关系

image-20220127002921342

router-view

是切换的时候是会走一遍生命周期的,有

  1. linkActiveClass: ‘mui-active’,linkActiveClass会在点击的router-link增加一个class属性

1-28day

eventLoopimage-20220128223128117

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rq2UXCEz-1645598896119)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220128223949647.png)]

微任务和宏任务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cHhhSdpT-1645598896120)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220129154815026.png)]

image-20220129155325396

image-20220129160926071

image-20220129161009289

localstorage

storage储存的意思

image-20220130163602305

image-20220130164104390

形成搜索记录

image-20220130164550860

image-20220130164609451

localstorage存的是Json数据

use()

image-20220201161838832

image-20220201162244827

1-30day

1.什么是跨域?

跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。

例如:a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注意:跨域限制访问,其实是浏览器的限制。理解这一点很重要!!!

同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;

过程已经请求了,已经响应了,但是浏览器不提供数据给我们使用

jsonp 利用了同源策略不会限制script 不会限制src的特性

服务器与服务器之间传输数据是用http传输,浏览器和服务器是用ajax请求

代理服务器:

前端本地是8080端口,服务器的资源是5050/student

加了代理服务器之后,前端的请求是8080/student,代理服务器是5050

加了一个atguigu可以发送给多个服务器

image-20220201180113176

image-20220201175807134

image-20220201175923276

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1qrmY57S-1645598896137)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220201175940877.png)]

image-20220201180903677

image-20220201181232517

关闭eslint语法

image-20220203171658706

vue3

0.拉开序幕的setup

  1. 理解:Vue3.0中一个新的配置项,值为一个函数。

  2. setup是所有Composition API(组合API)“ 表演的舞台 ”

  3. 组件中所用到的:数据、方法等等,均要配置在setup中。

  4. setup函数的两种返回值:

    1. 若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)

    2. 若返回一个渲染函数:则可以自定义渲染内容。(了解)

      import {h} from 'vue' 
      //返回一个渲染函数
         return  ()=>h('h1','硅谷')
      
  5. 注意点:

    1. 尽量不要与Vue2.x配置混用
      • Vue2.x配置(data、methos、computed…)中可以访问到setup中的属性、方法。
      • 但在setup中不能访问到Vue2.x配置(data、methos、computed…)。
      • 如果有重名, setup优先。
    2. setup不能是一个async函数,因为返回值不再是return的对象, 而是promise, 模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)

1.main.js

import { createApp } from 'vue'
// 2版本的是Vue构造函数,3是createdApp工厂函数,这是一个新的api
import App from './App.vue'
// import Vue from 'vue'

// mount挂载
// app会比vm更加轻量
// Vue构造函数在vue3中是没有定义的
const app=createApp(App)
app.mount('#app')

setTimeout(()=>{
  app.unmount()
},1000)
 new Vue({
 	render:(h)=> h(App)
 }).$mount('#app')

可以不用根标签

2.watch

3.ref

  // 情况一,监视ref的数据
    watch(
      name,
      (newval, oldval) => {
        console.log(newval, oldval)
      },
      {}
    )
    // 情况二:监视多个ref数据所定义的数据
    watch(
      [name, msg],
      (newval, oldval) => {
        console.log(newval, oldval)
      },
      { immediate: true, deep: true }
    )
 

4. reactive

监视一整个对象

// 三,监视reactive所定义的全部数据,oldval失效了,
    // 可以把需要监视的数据另外拿出来放到ref之中,这样就有oldval功能了
    // 默认开启了深度监视功能
    watch(person, (newval, oldval) => {
        console.log(newval, oldval)
      }, {})

监视一阵个对象里面的属性

// 情况四:监听reactive的某个属性,可以替代情况三
    watch(()=>person.name,(newval,oldval)=>{
        console.log(newval,oldval);
    },{})

监视一阵个对象里面的对象

watch(
      () => person.job,
      (newval, oldval) => {
        console.log(newval, oldval)
      },
      {deep:true}
    )

这里是reactive的某个对象(不是reactive),所以开启deep:true

对象类型获取不到oldval

5.computed

要有return返回值

let a=computed(()=>{
      return person.name+"-"+person.job.a
  })

6.watchEffect

从属性中拿值出来,然后变化属性,就会触发watchEffect函数

watchEffect(()=>{
      let a1=name.value
      console.log('触发了watchEffect',a1);
    })
  • watch的套路是:既要指明监视的属性,也要指明监视的回调。

  • watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。

  • watchEffect有点像computed:

    • 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
    • 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。

7.生命周期

vue2是先走beforecreate和create钩子函数,然后在寻找el或者$mount选项,而vue3一开始就要准备好createApp和mount函数,然后才走beforecreate和create钩子函数,相当于把mount提前到最开始

​ Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名: beforeDestroy改名为 beforeUnmount

​ destroyed改名为unmounted

Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:

  • beforeCreate===>setup()
  • created=======>setup()
  • beforeMount ===>onBeforeMount
  • mounted=======>onMounted
  • beforeUpdate===>onBeforeUpdate
  • updated =======>onUpdated
  • beforeUnmount ==>onBeforeUnmount
  • unmounted =====>onUnmounted

8.window添加删除事件

let page = reactive({
    x: 0,
    y: 0
  })
  function savepoint(event) {
    page.x = event.pageX
    page.y = event.pageY
    console.log(event.pageX, event.pageY)
  }
  onMounted(() => {
    window.addEventListener('click', savepoint)
  })
  onBeforeUnmount(() => {
    window.removeEventListener('click', savepoint)
  })

removeEventListener(),第一个删除是什么事件,第二个是函数(这个函数需要独立出来)

9.窗口的坐标

1、pageX和pageY:
	相对于浏览器中完全呈现内容区域的左上角。此参考点位于左上角的URL栏和后退按钮下方。这一点可以在浏览器窗口中的任何位置,
	并且如果在页面中嵌入了嵌入的可滚动页面并且用户移动滚动条,则实际上可以改变位置。

2、screenX和screenY:
相对于物理屏幕/监视器的左上角,只有增加或减少监视器数量或监视器分辨率时,此参考点才会移动。

3、clientX和clientY:
相对于浏览器窗口的内容区域(视口)的左上边缘。即使用户从浏览器中移动滚动条,此点也不会移动。

10.hook

hook函数,是对setup()里面的功能进行封装的,

建立一个hook文件夹,然后下面一个js文件

import { reactive,onMounted,onBeforeUnmount } from "vue"
export default function(){
 let page = reactive({
   x: 0,
   y: 0
 })
 function savepoint(event) {
   page.x = event.pageX
   page.y = event.pageY
   console.log(event.pageX, event.pageY)
 }
 onMounted(() => {
   window.addEventListener('click', savepoint)
 })
 onBeforeUnmount(() => {
   window.removeEventListener('click', savepoint)
 })
 return page
}

需要有return函数进行导出暴露,用函数包裹

import usepoint from '../hook/pomint'
export default {
  setup() {
    let show = ref(true)
    let page=usepoint() //这里相当于启动hook函数并且进行保存数据
    return { show ,page}

11. toRef和toRefs

这两个的作用就是方便使用,

toRef和Ref区别,就是toref都是使用person里面的,相当于桥接出来的数据

  let person = reactive({
      name: 'lqc',
      age: '18',
      job: {
        j1: {
          salary: 2000
        }
      }
    })
    console.log(person);
    console.log(toRef(person, 'name'))
    // console.log(person.name)
    // console.log(ref(person.name))
    return {
      name:toRef(person,"name"),
      age: toRef(person, 'age'),
      person,
      salary: toRef(person.job.j1, 'salary')
    }

image-20220209145629333

toRefs相当于多个toRef

下面相当于把person里面的属性,拆出来用属性return给页面

使用:

<div>
    <div>{{name}}</div>
    <div>{{age}}</div>
// 下面这里体现了toRefs的作用,只少了一个person层
	<div>{{job.j1.salary}}</div>
    <button @click="age++">addsalary</button>
    <button @click="name+='1'">+</button>
  </div>

return {
      name: toRef(person, 'name'),

      person,
      age: toRef(person, 'age'),
      salary: toRef(person.job.j1, 'salary'),
      ...toRefs(person)
    }

shallowReactive监视第一层的

ref,shoallow的value值是Proxy的话就是响应式的,如果不是proxy的类型,是object那就不是响应式

12.shallowReactive 与 shallowRef

  • shallowReactive:只处理对象最外层属性的响应式(浅响应式)。

  • shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理。

  • 什么时候使用?

    • 如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive。
    • 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换 ===> shallowRef。

13.readonly 与 shallowReadonly

  • readonly: 让一个响应式数据变为只读的(深只读)。(可以使reactive和ref只读),readonly的参数是响应式的数据
  • shallowReadonly:让一个响应式数据变为只读的(浅只读)。
  • 应用场景: 不希望数据被修改时。
let person = reactive({
      name: 'lqc',
      age: '18',
      job: {
        ppp:1,
        j1: {
          salary: 2000
        }
      }
    })
    person=readonly(person)
    console.log(person);

readonly的person会把对象的person覆盖,导致无法修改数据

14.toRaw 与 markRaw

心得:普通数据到响应式数据的是ref,reactive.从响应式数据到普通数据是toRaw

  • toRaw:
    • 作用:将一个由reactive生成的响应式对象转为普通对象
    • 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
  • markRaw:
    • 作用:标记一个对象,使其永远不会再成为响应式对象。
    • 应用场景:
      1. 有些值不应被设置为响应式的,例如复杂的第三方类库等。
      2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。

15.provide 与 inject

心得:数据通信有props,emit,还有mibus传递方式,现在感觉这个可以更好的传值,可以替代minibus

  • 作用:实现祖与后代组件间通信

  • 套路:父组件有一个 provide 选项来提供数据,后代组件有一个 inject 选项来开始使用这些数据

  • 具体写法:

    1. 祖组件中:

      setup(){
      	......
          let car = reactive({name:'奔驰',price:'40万'})
          provide('car',car)
          ......
      }
      
    2. 后代组件中:

      setup(props,context){
      	......
          const car = inject('car')
          return {car}
      	......
      }
      

16.响应式数据的判断

  • isRef: 检查一个值是否为一个 ref 对象

  • isReactive: 检查一个对象是否是由 reactive 创建的响应式代理

  • isReadonly: 检查一个对象是否是由 readonly 创建的只读代理

  • isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理

    readonly返回的也是一个proxy对象

Composition API 的优势

1.Options API 存在的问题

使用传统OptionsAPI中,新增或者修改一个需求,就需要分别在data,methods,computed里修改 。

2.Composition API 的优势

我们可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起,要配合hook函数使用,才能发挥组合式api的作用,就是根据业务功能打包,不需要在data,methods,watch大量的数据之中寻找需要的方法,组合式api封装在一起就节约了寻找的时间

function就是一个hook函数

2.Teleport

  • 什么是Teleport?—— Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。

  • 原因在于如果我们嵌套在 Vue 的某个组件内部,那么处理嵌套组件的定位、z-index 和样式就会变得很困难(用于处理嵌套组件内部的复杂定位问题,)

    <teleport to="移动位置">
    	<div v-if="isShow" class="mask">
    		<div class="dialog">
    			<h3>我是一个弹窗</h3>
    			<button @click="isShow = false">关闭弹窗</button>
    		</div>
    	</div>
    </teleport>
    

3遮罩层

<template>
  <teleport to="body">
    <div class="mask" v-if="status">
      <div class="diolang">
        弹窗
        <div>内容1</div>
        <div>内容2</div>
        <div>内容4</div>
      </div>
    </div>
  </teleport>
  <button @click="status=!status">change</button>
</template>

<script>
import { ref } from 'vue'
export default {
  setup() {
    let status = ref(false)
    return {
      status
    }
  }
}
</script>

<style scoped>
.mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: black;
  opacity: 0.5;
}
.diolang {
  position: absolute;
  width: 100px;
  background-color: bisque;
  top: 45%;
  left: 45%;
}

</style>

遮罩底层在遮住整个屏幕,被遮罩层

4.Suspense

  • 等待异步组件时渲染一些额外内容,让应用有更好的用户体验

  • 因为都是用同步的话,其实组件都是一起出现的,只要有一个出现的慢,全部就不会出现,一直等待那个最慢的组件.

  • 使用这个的话,组件出现的速度会变慢一些

  • 使用步骤:

    • 异步引入组件

      import {defineAsyncComponent} from 'vue'
      const Child = defineAsyncComponent(()=>import('./components/Child.vue'))
      
    • 使用Suspense包裹组件,并配置好defaultfallback

      <template>
      	<div class="app">
      		<h3>我是App组件</h3>
      		<Suspense>
      			<template v-slot:default>
      				<Child/>
      			</template>
      			<template v-slot:fallback>
      				<h3>加载中.....</h3>
      			</template>
      		</Suspense>
      	</div>
      </template>
      

      default是出现后显示的,fallback是出现前显示的,使用异步组件的话,需要使用Suspense标签

      异步组件

      APP.vue

      <template>
        <div class="father">
          父组件
          <Suspense>
            <template v-slot:default>
              <children></children>
            </template>
      
            <template v-slot:fallback>
              <h2>加載中</h2>
            </template>
          </Suspense>
        </div>
      </template>
      
      <script>
      // import children from './components/children.vue'
      import { defineAsyncComponent } from 'vue'
      const children = defineAsyncComponent(() => import('./components/children.vue'))
      export default {
        components: {
          children
        }
      }
      </script>
      
      <style>
      .father {
        width: 200px;
        /* height:200px; */
        background-color: orange;
      }
      </style>
      

      Children.vue

      <template>
        <div class="children">
          子组件 
          {{num}}
        </div>
       
      </template>
       
      <script>
      import Son from '../components/Son.vue'
      export default {
        name:"Chilren",
        components: {
          Son
        },
        async setup(){
          let num=10
          let a=new Promise((resolve,reject)=>{
            setTimeout(()=>{
              resolve({num})
            },1000)
          })
          return await a
        }
      }
      </script>
      
      <style scoped>
      .children {
        width: 150px;
        /* height: 170px; */
        background-color: red;
      }
      </style>
      

      await是相当于then拿到请求之后的结果

Typecript

  • const是对let的一个增强,它能阻止对一个变量再次赋值。

  • props: { todo: Object as ()=> Todo }, 函数返回的是Todo接口类型

  • const state = reactive<{todos:Todo[]}>({todos:[ {} ,{},{} ]})

  • interface Person1{
        name: string,
    }
    
    let p1: Person1 = {
        name:'java'
    }
    
    let p2 = p1
    p2.name=12 //这里会报错,因为p2和p1使用的是同一个堆内存中的数据,类型保护的是堆内存中的数据
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@追求卓越

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值