当前位置: 首页 > news >正文

Vue基础记录

Vue

整体要学的
vue基础
vue-cli
vue-router
vuex
element-ui
vue3

简介

特点:

  1. 组件化
  2. 声明式编码
  3. 使用虚拟dom + 优秀Diff算法

在这里插入图片描述
在生成真实dom的时候,会先有一部虚拟dom,且新的虚拟dom会和旧的虚拟dom进行diff算法比较
如果有些dom没改,那么就可以不用再重新渲染了,提高性能

环境

安装node

node -> 16.20.2

切换淘宝镜像

npm install -g cnpm -registry=http://registry.npm.taobao.orgnpm config set registry http://registry.npm.taobao.org/

使用了第二个,下一步才有用

安装vue

npm install -g @vue/cli

在这里插入图片描述

vscode中不给运行vue解决办法

set-ExecutionPolicy RemoteSigne 

问题就是脚本的执行策略不行,应该是安全问题

创建vue项目

create vue jplan

vue还不给输入大写

选自己的配置

Vuex + router + CSS Pre-processors

版本

2.x

路径选择

history router no

css预处理语言 less

配置文件 -> package.json

启动

npm run serve

引入element-ui

引入

npm i element-ui -S

目录下必须有package.json

在 main.js 中写入以下内容:

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';Vue.use(ElementUI);new Vue({el: '#app',render: h => h(App)
});

引入Axios

安装

npm install axios
npm install vue-axios

main.js引入

//引入axios
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios,axios)

开发者工具devtools

vue2 只能用vue-devtools

Vue核心

模版语法

插值语法
{{ xxx}}

指令语法
v-bind 简写是 :xxx

数据绑定

单向的是 :value=" "
双向的是 v-model:value=" " 简写是 v-model=" "

v-model绑定的值不能是props传来的值,因为props传来的值是不可修改的
特别是对象的值,修改了props,别人还不知道,这不完蛋了吗

data的两种写法

对象式

    <script type="text/javascript">Vue.config.productionTip = false; //阻止vue启动时生成生产提示new Vue({el: "#app",data: {msg: 'wo de fuck'}})</script>

函数式

    <script type="text/javascript">Vue.config.productionTip = false; //阻止vue启动时生成生产提示new Vue({el: "#app",data() {return {msg: 'hi'}}})</script>

像一个函数返回一个对象

一般使用函数式,组件开发的时候必须写函数式,所以以后写函数式就ok

MVVM

Vue没有完全遵循MVVM,受启发

在这里插入图片描述

M 是 Model 模型,也就是我们的数据
V 是 View 视图,模版的代码 ->我们自己写的代码
VM 是视图模型,也就是Vue

Vue类似于数据和视图之间的中间商,我们在js代码中写的data会出现在vm里边,我们在{{}}模版语法里边可以获取到这些数据

在vm里边会有监听器,监听dom

Object.defineProperty()

Object.defineProperty(obj, prop, descriptor)

obj
要定义属性的对象。

prop
一个字符串或 Symbol,指定了要定义或修改的属性键。

descriptor
要定义或修改的属性的描述符。

描述符
1.configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,默认值为false。

2.enumerable:能不能枚举,这里就是能不能for遍历,默认值为false

3.writable:表示能否修改属性的值。默认值为false。

4.value:包含这个属性的数据值。默认值为undefined。
举例

let p = {}
object.defineProperty(p,'age',{...
})

configurable 不能delete p.age
writable 不能 p.age = 12,这样是无效的
value是设置值

get,set
读取函数时调用get

写入属性时调用set

例如,假如我们想让对象p的age值变成响应式的,就可以使用get

    <script>let num = 1;let p = {name: 'jjking'}Object.defineProperty(p,"age",{enumerable: true,get() {console.log('获取值,此处是相当于是响应式的');return num;}})console.log(p);</script>

需要注意的是,get函数不能和属性value共存,会报错
这里如果我们之后修改num,重新获取age的值的话,就会更新

如何定义多个属性

var student = {};
Object.defineProperties(student,{name:{writable:false,value:"lisi"},age : {writable:true,value : 16,},sex:{get(){return '男';},set(v){p1.sex = v}}
})

数据代理

最简单的数据代理
通过一个对象代理对另一个对象属性的操作(读/写)

    <script>let obj1 = {x:100}let obj2 = {y:200}Object.defineProperty(obj2,'x',{get() {return obj1.x;},set(value) {obj1.x = value;}})</script>

此时我们就可以使用obj2来操作obj1了,并且obj1自己的改变,也会改变obj2的x值

在这里插入图片描述

  1. vue先是把data里边的数据放到vm里边,但是名字叫_data
  2. 然后通过Object.defineProperty()代理所有属性的操作,也就是这里的vm.name,和vm.address,这两个是代理对象

事件处理

基本使用
@xxx: 函数名

阻止默认时间prevent

    <div id="app"><a href="www.baidu.com" @click="showInfo">点我</a></div><script type="text/javascript">const vm = new Vue({el: '#app',data: {},methods: {showInfo(e) {e.preventDefault();alert("同学你好!");}}})</script>

a标签的默认事件是跳转
我们可以直接写e.preventDefault();

也可以用vue的@click.prevent

@click.prevent="showInfo"

事件冒泡
原生的写法

    <div id="app"><div @click="showDiv"><button @click="showInfo">点我</button></div><script type="text/javascript">const vm = new Vue({el: '#app',data: {},methods: {showDiv() {alert("DIV你好!");},showInfo(e) {e.stopPropagation();alert("同学你好!");}}})</script>

此时点button的话,他包裹的div也会触发时间showDiv,这就是冒泡

使用vue

@click.stop="showInfo"

事件只触发一次once

@click.once="showInfo"

事件捕获
capture

        <div @click.capture="showDiv"><button @click.stop="showInfo">点我</button></div>

正常来说,是先捕获,再冒泡
也就是 先div,再button
如果使用.capture的话,就会先执行div,再执行button

    <div id="app"><div @click.capture="showDiv"><button @click="showInfo">点我</button></div><script type="text/javascript">const vm = new Vue({el: '#app',data: {},methods: {showDiv() {alert("DIV你好!");},showInfo() {alert("同学你好!");}}})</script>

在这里插入图片描述
在这里插入图片描述
事件当前操作元素才触发self

如上也是,只有当我们点击的是div的时候,才触发事件,点button冒泡过去的话,是不会触发事件的

        <div @click.self="showDiv"><button @click="showInfo">点我</button></div>

这个方法也可以防止冒泡

passive:事件的默认行为立即执行,无需等待事件回调执行完毕:

有一些@事件,他会先去处理方法,如果方法里边耗时很久的话,不执行默认行为就会有卡顿,所以passvie可以解决这个问题

如果需要多个事件处理
@click.prevent.stop
顺序无所谓

键盘事件

keydown,按下去就触发事件

keyup,按下去,抬上来之后才出发事件

event:当前事件

event.target:当前事件操作的元素

event.target.value 这是这个例子中input的value

    <div id="app"><input type="text" @keyup.enter="showInfo"></div>
...方法showInfo(e) {console.log(e.target.value);}

keyup.enter 的意思是,检测到回车才触发事件

常用的别名
Vue中常用的按键别名:
回车=>enter
删除=>delete(捕获“删除”和“退格”键)
退出=>esc
空格=>space
换行=>tab
上=>up
下=>down
左=>1eft
右=>right

计算属性

要用的属性不存在,需要自己计算得来
原理是: Object.defineProperty 提供的getter 和 setter

get方法调用的时机(1) 初次读取的时候 (2) 依赖的 数据发生变化的时候

和methods相比,优势是有缓存机制,效率高

计算属性在vm身上,直接调即可

<script type="text/javascript">new Vue({el: '#root',data: {firstName: '',lastName: ''},computed: {fullname: {get() {return this.firstName + '-' + this.lastName}}}})
</script>

简写只有get方法的时候

            methods: {fullname(){return this.firstName+this.lastName}}

set方法

set方法里边我们必须使得计算属性的依赖的数据发生改变,整体才会改变

    <div id="app"><input type="text" v-model="firstName"> <br><input type="text" v-model="secondName"><div>{{fullName}}</div></div><script type="text/javascript">const vm = new Vue({el: '#app',data: {firstName: "",secondName: ""},computed: {fullName: {get() {return this.firstName + "-" + this.secondName},set(value) {const arr = value.split("-");this.firstName = arr[0];this.secondName = arr[1];}}}})</script>

如果没改变get方法中的firstName 和 secondName,计算属性走的还是缓存

监视属性

写法

    <div id="app"><div>今天天气{{info}}</div><button @click="change">change</button></div><script type="text/javascript">const vm = new Vue({el: '#app',data: {isHot: false},computed: {info() {return this.isHot ? '炎热' : '凉爽';}},methods: {change() {this.isHot = !this.isHot;}},watch:{isHot: {handler(newValue,oldValue) {console.log(newValue,oldValue);}}}})</script>

我们在watch里边直接写,isHot发生变化,就会执行handler里边的方法

另外一种写法

    <script type="text/javascript">const vm = new Vue({el: '#app',data: {isHot: false},computed: {info() {return this.isHot ? '炎热' : '凉爽';}},methods: {change() {this.isHot = !this.isHot;}}})vm.$watch('isHot',{handler(newValue,oldValue) {console.log(newValue,oldValue);}})</script>

在外边写也可以,只不过要注意的是,这里的isHot必须加引号

深度监视
如果我们要监视一个对象里边的数据的改变,需要加上配置项,deep:true

    <script type="text/javascript">const vm = new Vue({el: '#app',data: {numbers: {a: 1,b: 2}},watch: {numbers: {immediate:true,deep: true,handler(newValue, oldValue) {console.log('numbers发生变化',newValue,oldValue);}}}})</script>

绑定样式

适用于class和style

最简单的写法

 <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 --><div class="basic" :class="mood" @click="changeMood"></div>

数组的绑定
绑定class样式–数组写法,适用于:要绑定的样式个数不确定、名字也不确定

   <div class="basic" :class="['atguigu1','atguigu2']"></div>

对象的写法
适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用

<div class="basic" :class="{atguigu1:false, atguigu2:false}"></div>

简写
只有handler的时候,可以直接写

//原来的
watch: {numbers: {handler(newValue, oldValue) {console.log('numbers发生变化',newValue,oldValue);}}
}
//修改后的:
watch: {numbers(newValue, oldValue) {console.log('numbers发生变化',newValue,oldValue);}
}

computed 和 watch的区别
computed能实现的,watch都能实现,但是watch可以做异步操作

两个原则:

  1. 被vue管理的函数写成普通函数,this指向的是vm或者组件实例对象
  2. 所有不被vue所管理的函数,最好写成箭头函数,此时this指向的是vm或者组件实例对象

这里因为如果不被vue管理的函数写成普通函数,this指向的会是window

class 和 style样式

    <div id="root"><!-- 字符串写法,适用于:样式的类名不确定,需要动态指定 --><div class="basic" :class="mood">{{number.a}}</div><!-- 数组写法,适用于:要绑定的样式个数不确定,名字也不能确定 --><div class="basic" :class="moodArr">{{number.b}}</div><!-- 对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 --><div class="basic" :class="moodObj">{{number.b}}</div></div>
...
data:{number:{a:1,b:2,},mood:'happy',moodArr:['happy'],moodObj:{happy:true}},

style的绑定和class的绑定一致

条件渲染

v-if,整个节点不在了
v-show 节点还在,只是隐藏

		<h1 v-if="n===1">1</h1><h1 v-if="n===1">2</h1><h1 v-if="n===1">3</h1>

如果条件一样,我们可以再外边写一个div

<div v-if="n===1"><h1>1</h1><h1>2</h1><h1>3</h1>
</div>

但是有可能会破坏结构,所以用template

<template v-if="n===1"><h1>1</h1><h1>2</h1><h1>3</h1>
</template>

template只能和v-if使用

列表渲染

v-for
      <!-- 遍历数组 -->在遍历数组时,数组元素后面的一个参数,是遍历时的key值,因为我们这里没有自定义key,所以默认是012<ul><li v-for="(person,index) in persons">{{index}}--{{person.name}}--{{person.age}}</li></ul><!-- 遍历对象 -->遍历对象时,括号中第一个参数是对象中键值对的值,第二个参数是键值对的键,第三个参数是这个这条遍历的数据的key<ul><li v-for="(value,key,index) in car">{{index}}--{{key}}--{{value}}</li></ul>遍历字符串时,括号中第一个参数是字符串这个位置的值,第二个参数是这个这条遍历的数据的key<!-- 遍历字符串 --><ul><li v-for="(value,key) in str">{{key}}--{{value}}</li></ul>...data: {persons: [{ id: "001", name: "ice", age: "13" },{ id: "002", name: "peach", age: "12" },],car: {speed: "20km/h",year: "2014",},str: "i am a word",},
key的原理和使用

key的内部原理

  1. 虚拟dom中key的作用:
    key是虚拟dom对象的标识,vue会根据新数据生成新的虚拟dom,随后进行diff算法
  2. 对比规则:
    (1) 旧的虚拟dom和新的虚拟dom,有相同key
    a. 如果虚拟dom中内容没变,则直接复用之前的真实dom
    b.如果内容变化,则生成新的dom
    (2)没有相同key,创建新的dom

在这里插入图片描述

看这个图就知道为什么index作为key,如果有逆序操作的时候,会出现界面问题了

两边新旧都有虚拟dom,此时进行diff比较,我们新的是逆序添加了老刘这条li

key相同都是0,input也相同,只有张三-18老刘-30不同,此时input相同

那么不同的内容,老刘-30会创建新的dom
对于相同的内容,input输入框,就会复用之前的dom,也就是原本应该是张三的输入框

以此类推,这里整个往上移,就会出现页面问题

解决办法也很简单,就是我们绑定key的时候,用可以唯一标识的key,比如id,身份证,手机号等等

如果不存在对数据的逆序,破坏顺序操作,用index也是没有问题的

列表过滤

实现列表过滤的效果
在这里插入图片描述

watch监视

    <div id="app"><label>姓名:</label><input v-model="name"><ul><li v-for="(person) in persnsOfSearch">{{person.name}}--{{person.age}}</li></ul></div><script type="text/javascript">const vm = new Vue({el: '#app',data: {name: '',persnsOfSearch: [],persons: [{ id: '001', name: 'ice', age: '17' },{ id: '002', name: 'ipeach', age: '18' },{ id: '003', name: 'icepeach', age: '19' }]},watch: {name: {immediate: true,handler(newValue, oldValue) {console.log('输入发生变化');this.persnsOfSearch = this.persons.filter((p) => {return p.name.indexOf(newValue) != -1;})}}}})</script>

整体的写法就是
输入框的里边的值,我们监视他
如果发生变化,也就是传来新的值newValue,我们就去过滤数组,
过滤的条件是,在persons数组中,查找每个对象的name是否含有newValue

利用的是函数 str.indexOf(val) ,如果有就会返回位置,如果没有就会返回-1
所以只有 != -1,就说明含有该值,filter通过

最后我们把过滤好的数据传给persnsOfSearch ,不用原来的数组就是为了不破坏数据

计算属性实现

    <div id="app"><label>姓名:</label><input v-model="name"><ul><li v-for="(person) in persnsOfSearch">{{person.name}}--{{person.age}}</li></ul></div><script type="text/javascript">const vm = new Vue({el: '#app',data: {name: '',persons: [{ id: '001', name: 'ice', age: '17' },{ id: '002', name: 'ipeach', age: '18' },{ id: '003', name: 'icepeach', age: '19' }]},computed: {persnsOfSearch() {return this.persons.filter((p) => {return p.name.indexOf(this.name) != -1;})}}})</script>

我们如果使用计算属性的话就可以快速的解决这个问题

第一,我们得监视name的改变,这里的监视name的改变,巧妙的把name写到计算属性里边了,计算属性里边,依赖的数据发生改变,那么计算属性也会发生改变

也就是我们这里的persnsOfSearch,里边依赖着this.name

第二,我们做过滤

还有一个好处就是,我们不用像watch那样还得写immediate:true,计算属性一开始就会去进行计算

排序

在这里插入图片描述
在上面的基础上,加上一个age过滤的功能

    <div id="app"><label>姓名:</label><input v-model="name"><ul><li v-for="(person) in persnsOfSearch">{{person.name}}--{{person.age}}</li></ul><button @click="sortType = 0">原顺序</button><button @click="sortType = 1">降序</button><button @click="sortType = 2">升序</button></div><script type="text/javascript">const vm = new Vue({el: '#app',data: {name: '',persons: [{ id: '001', name: 'ice', age: '17' },{ id: '002', name: 'ipeach', age: '18' },{ id: '003', name: 'icepeach', age: '19' }],sortType: 0    },computed: {persnsOfSearch() {const arr = this.persons.filter((p) => {return p.name.indexOf(this.name) != -1;})//是否是原来的顺序if(this.sortType != 0) {arr.sort((p1,p2) => {return this.sortType == '1' ? p2.age - p1.age : p1.age - p2.age;}) } return arr;}}})</script>

获取表单数据

<input type="text"/>v-model收集的是value值,用户输入的就是value值
<input type="radio"/> v-model收集的是value值,我们必须给标签设置value值
<input type="checkbox"/>

  1. 如果没有设置value值,收集的是checked值(布尔)
  2. 如果设置了value值
    (1)v-model的初始值不是数组,收集的就是checked
    (2)v-model的初始值是数组,收集的就是value组成的数组

备注: v-model的三个修饰符
lazy: 失去焦点的再收集数据
number: 输入字符串转为有效数字
trim: 去掉首尾空格

生命周期在这里插入图片描述

beforeCreate 是数据代理监测和数据代理创建之前,不是vm

beforeMount 此时只有虚拟dom,所以此时没有把虚拟dom转换为真实dom

beforeUpdate 此时数据是最新的,但是页面是旧的

beforedestroy 此时数据,方法都在,但是此时如果修改数据,方法是不会触发数据更新流程
一般这个时候,清除定时器,解绑自定义事件,取消订阅等等

注意
销毁之后,只是vm没了,但是真实dom还是存在的,也就是vm的工作成果还在,不过管理的他的vue死了


http://www.mrgr.cn/news/80131.html

相关文章:

  • 海康萤石摄像机接入EasyNVR流程:开启RTSP-》萤石视频添加到EasyNVR-》未来支持海康SDK协议添加到EasyNVR
  • 代码随想录算法训练营第三天 | 链表理论基础 | 707.设计链表
  • 从整个SecurityFilterChain的角度,一个请求经过Spring Security的流程
  • L23.【LeetCode笔记】验证回文串(剖析几种解法)
  • Spring 如何解决循环依赖?
  • Linux下socket广播通讯的实现
  • 图像融合算法笔记2024 CDTNet
  • pytorch_fid 安装笔记
  • 【AIGC】ChatGPT保护指令:高效提升GPTs提示词与知识库文件的安全性
  • 【PyCharm调试】显示一个对象值时会调用的方法
  • 长短期记忆神经网络(LSTM)介绍
  • 【ADS射频电路学习笔记】1. ADS基本操作
  • PHP搭建环境
  • depth wisepoint wise
  • 【收藏】Cesium 限制相机倾斜角(pitch)滑动范围
  • faster-RCNN训练【环境配置→自建数据集→训练→改错】
  • C语言实现八大排序算法
  • 【C语言】库函数常见的陷阱与缺陷(六):输入输出函数
  • kubeadm安装K8s集群之高可用组件keepalived+nginx及kubeadm部署
  • OSPF协议