【前端】Vue学习笔记

loader版本


"less": "^4.0.0",
"less-loader": "^7.0.0",  (8以下均可)

常见问题

组件不显示

1.template中的内容必须包含在一个div中。
2.组件名称渲染时不可为HTML标签,例如header、footer等等
如需使用,只要和标签名不一样就行,比如Header、Footer等等

快捷键

1.vdata

data() {
    return {
      key: value
    }
  },

2.vcomputed

computed: {
    name() {
      return this.data;
    }
  },

Vue中常用的数组方法

https://blog.csdn.net/wang_xiao_ye/article/details/89385023

基础

Vue全面知识点速查:https://blog.csdn.net/qq_44317018/article/details/104146747

插值语法 {{}}

原理:
(1). 首次加载页面内容时,会用data中同名变量的初始值代替{{变量名}}位置
(2). 当data中同名变量在new Vue()中被更改时,自动更新{{变量名}}位置为新值

{{}}中可以放什么,不能放什么
(1). 可以放: 变量,表达式,有返回值的函数调用,创建对象,访问数组元素,三目运算
(2). 不能放: 程序结构(分支和循环),没有返回值的函数调用

v-if

根据表达式的值的 truthiness 来有条件地渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 ,将提出它的内容作为条件块。

	<el-form-item label="会员模型" v-if="modelForm.modelType===1">
        <el-checkbox-group v-model="modelForm.modelTypes">
          <el-checkbox :label="2" name="modelTypes">月会员</el-checkbox>
          <el-checkbox :label="3" name="modelTypes">年会员</el-checkbox>
        </el-checkbox-group>
      </el-form-item>

modelForm{
	modelTypes:[]
}
当元素隐藏时,modelForm.modelTypes会被重置为初始值 (没有设置初始值会被重置为null

v-bind

如果元素的属性值希望动态改变:
(1). 问题: 不能用{{}}绑定
(2). 解决: 应该用v-bind指令:
a. 标准写法: <元素 v-bind:属性名="JavaScript表达式"> 这里常用函数、赋值操作
b. 强调: 一定不要加{{}},属性名前加v-bind:,=后的"“就扮演了{{}}的角色!{{}}中能写什么,此时" "中就能写什么!
c. 简写: 其实v-bind可省略!但是:不能省略!<元素:属性名=“js表达式”>

字符串拼接

外双内单或者发过来也可以

v-on绑定事件 缩写@
v-bind绑定属性 缩写: 英文冒号
属性前加一个英文冒号:src="imgURL" 会把字符串变成变量
例如:自定义属性="true" 此时true为布尔值

v-on

a. 标准写法: <元素 v-on:属性名="JavaScript表达式"> 这里常用函数、赋值操作
b. 强调: 一定不要加{{}},属性名前加v-on:,=后的"“就扮演了{{}}的角色!{{}}中能写什么,此时" "中就能写什么!

v-model

【前端】Vue学习笔记_第1张图片

https://www.cnblogs.com/mark5/p/11603428.html

v-model本质上是一个语法糖。如下代码本质上是,其中@input是对输入事件的一个监听,:value="test"是将监听事件中的数据放入到input,
下面代码是v-model的一个简单的例子。在这边需要强调一点,v-model不仅可以给input赋值还可以获取input中的数据,而且数据的获取是实时的,因为语法糖中是用@input对输入框进行监听的。可以在如下div中加入

{{ test}}

获取input数据,然后去修改input中数据会发现

中数据随之改变。


<div id="app">
 <input v-model="test">
 <input :value="test" @input="test= $event.target.value">
 <p>{{ test}}p>
div>
<script src="/resources/js/vue.js">script>
<script>
 new Vue({
   el: '#app',
   data: {
     test: '这是一个测试'
   }
 });
script>

数组中响应式的方法

(5) 坑: 如果v-for遍历的是数组时,在程序中通过下标修改数组元素值,页面上的HTML元素不会自动更改!
比如: this.teachers[0]=“燕儿” 页面上是不会变的!
因为数组中的数字类型的下标012…无法添加访问器属性,也就不受监控!
解决: 今后,vue中修改数组中的元素值!必须用数组相关的函数(push,pop),才能自动更新页面。因为函数都是受监控的。
比如: this.teachers.splice(0,1,“燕儿”)
删除0位置的1个元素,再在0位置放入"燕儿"
结果: 页面会自动变化!

函数传递参数

$event是vue提供的特殊变量,用来表示原生的事件参数对象 event。$event可以解决事件参数对象 event被覆盖的问题。

// 传递参数获取到当前元素
//原生js
//this指向当前元素
在onclick = "fn(this)"
 
//Vue中使用方法  顺序不强制要求,但建议第一个为$event
v-on:click="fn($event,parm)"

无参数时 fn($event) 与 fn 作用一样
fn 默认会传一个 $event 参数

methods: {
    fn: function (e,value) {
        // 当前html元素
        e.currentTarget; // 点击事件绑定在哪一个元素上,currentTarget获取到的就是哪一个元素。
        e.target // 当前点击的是哪一个元素,target获取到的就是哪一个元素
        // 变成DOM元素
        $dom=$(e.currentTarget)
    }
}

如果是表单元素
例如checkbox
<input type="checkbox" @change="onCheckBoxChange">
onCheckBoxChange(e){
	e.target.checked // true / false
}

$refs

引用DOM

一般来讲,获取DOM元素,需document.querySelector(".input1") 获取这个dom节点,然后在获取input1的值。

但是用ref绑定之后,我们就不需要在获取dom节点了,直接在上面的input上绑定input1,然后$refs里面调用就行。

然后在javascript里面这样调用:this.$refs.input1这样就可以减少获取dom节点的消耗了

<div id="app">
  <input type="text" ref="input1"/>
  <button @click="add">添加</button>
</div>
 
<script>
new Vue({
  el: "#app",
  methods:{
  add:function(){
    this.$refs.input1.value ="22"; //this.$refs.input1 减少获取dom节点的消耗
    }
  }
})
</script>

更多用法
https://www.jianshu.com/p/899b684174a5

引用组件

应用场景:在父组件中直接调用子组件的方法
https://www.cnblogs.com/yuzhongyu/p/10825824.html
【前端】Vue学习笔记_第2张图片

$nextTick()

【前端】Vue学习笔记_第3张图片

路径问题

webpack资源处理的规则,分为相对路径,没有前缀的路径,带~的路径,相对根目录的路径

1.相对路径: "./assets/logo_blue.png" 

2.没有前缀的路径 "assets/logo_blue.png" 被webpack解析为相对路径

常用
3.~的路径  "~@/assets/theme/logo_blue.png" 被webpack解析为 require(src/assets/theme/logo_blue.png) 动态引入 
@在webpack 被resolve.alias配置下等价于/src

4.相对根目录的路径 "/assets/logo_blue.png" webpack不解析

vue-cli项目中使用别名:“@”和“~”的坑:https://blog.csdn.net/weixin_42060658/article/details/103654249

watch

watch: {
    $route: 'getAllGoods'  // 监听路径改变    参数为字符串 写函数名即可
},
method:{
  getAllGoods(){
  
  }
}

Vuex

mutation 改变  mutation 都是同步事务
Action 类似于 mutation,不同在于:
	Action 提交的是 mutation,而不是直接变更状态。
	Action 可以包含任意异步操作。

mapState

mapState 函数返回的是一个对象
...是扩展运算符

// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'
computed:{
 	// 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // 需要的属性
  })
}

示例:
computed:{
	//映射哪些字段就填入哪些字段
	...mapState(['nickname','age','gender']) 
}

computed:{
	// 那一句代码就相当于下面这些
	nickname(){return this.$store.state.nickname}
	age(){return this.$store.state.age}
	gender(){return this.$store.state.gender}
}

mapMutations


method:{
	//等同于this.$store.commit('ADD')
	...mapMutations(['ADD']),
	
	addNum(){
		//等同于this.$store.commit('ADD',{num:1})
		this.ADD({num:1})	
	}
}

router和route

图文:https://junshuai.blog.csdn.net/article/details/105699705

  • $route是代表处于激活状态的路由
    route是路由信息对象,里面主要包含路由的一些基本信息,包括
    name、meta、path、hash、query、params、fullPath、matched、redirectedFrom

官方文档:https://router.vuejs.org/zh/api/#%E8%B7%AF%E7%94%B1%E5%AF%B9%E8%B1%A1%E5%B1%9E%E6%80%A7


$route获取的是当前url地址的信息,通过$route可以拿到的数据包括

fullPath: "/Namevue/test"   // 包含查询参数和 hash 的完整路径。

router: ""     //路由规则所属的路由器

name: "Namevue"    //当前路径的名字,如果没有使用具名路径,则名字为空

// params传递参数需要在路由文件中进行配置,例如  path: detail/:id"
params: {id: "test"}    //路由中的定义的动态片段和全匹配片段的键值对

path: "/Namevue/test"    //当前路由对象的路径,会被解析为绝对路径,如 "/home/news"

query: {}   //路由中查询参数的键值对。例如,对于 /home/01?favorite=yes ,会得到$route.query.favorite == ‘yes‘ 。

hash //当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。

matched  类型: Array<RouteRecord>
一个数组,包含当前路由的所有嵌套路径片段的路由记录。
路由记录就是 routes 配置数组中的对象副本 (包括 children 和 meta** )。
可以控制台输出看一下有什么参数

redirectedFrom  如果存在重定向,即为重定向来源的路由的名字

***
meta 元数据字段,我们可以在这里配置一些自定义信息,例如网页标题
一般配合路由跳转使用
https://www.cnblogs.com/yuxi2018/p/11967281.html

  • $router
    router是VueRouter的实例,包含了一些路由的跳转方法,钩子函数等

路由守卫

官方文档:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html

路由元信息meta

https://router.vuejs.org/zh/guide/advanced/meta.html

// router
	{
        path: '/user',
        name: 'User',
        component: () => import('../views/user/User'),
        meta:{
            // 自定义参数
            auth:true 
        }
    }

// main.js
// 守卫
router.beforeEach((to,from,next)=>{
  // 和路由的meta自定义参数对应
  // some() 方法会依次执行数组的每个元素,第一个参数为数组里面的元素
  if (to.matched.some(item=> item.meta.auth)){
    // 未登录
    next({
      path:'/login',
      query:{
        redirect:to.fullPath
      }
    })
  }else{
    next() // 放行
  }
})

matched 待定

meta

路由跳转和传参 ***

在方法中使用$route前面是需要加this的,在元素中使用是不用加

元素中
<el-button type="primary" @click="$router.push({path: '/role'})">权限管理el-button>

方法中
<el-button type="primary" @click="skip">权限管理el-button>

method:{
	skip() {
      	this.$router.push({path: '/role'})
    },
}

(1)路由的跳转

根据路由名字跳转 this.$router.push({name:'B'})  


根据路由路径跳转 this.$router.push({path:'/B'})
简写:this.$router.push('/B')  

嵌套路由

{
    path: '/user',
    component: User,
    children: [
        {
            path: 'profile',
            component: UserProfile
        },
        {
            path: 'posts',
            component: UserPosts
        }
    ]
}

1.user/profile内跳转到posts

this.$router.push({path:'posts'})  // 不用加父路径


(2)路由的跳转并传参

参考:https://www.cnblogs.com/fanfanZhao/p/12203152.html vue的params和query两种传参方式及URL的显示

解释:前台和后台的数据交互。前台各个组件之间的数据传递。

  • 根据路由名字跳转传参
 

发送数据  this.$router.push({name:'B',params:{a:1,b:2}})

接收数据  `this.$route.params.a`   `this.$route.params.b`

简写:this.$router.push('/user/' + this.userId)

实例1:参数值在url中显示

首先需要对应路由配置如下:
{
    path: '/user/:id',
    name: 'user', // 组件别名
    component: user  // 组件名
}

const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
简写 router.push({ path: `/user/${userId}` }) // -> /user/123  最常用
接收数据  `this.$route.params.userId `


实例2:参数值不在url中显示

不需要修改路由

const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user
// 这种方式不行 router.push({ path: `/user/${userId}` }) 
接收数据  `this.$route.params.userId `

缺点:刷新会丢失数据

注意:如果提供了path,params 会被忽略。这个规则也适用于 router-link 组件的 to 属性。
因为params只能用name来引入路由,如果这里写成了path,接收参数页面会是undefined!!!

// 这里的 params 不生效
router.push({ path: '/user', params: { userId }})

  • 根据路由路径跳转传参

发送数据 路径为 B?c=3&d=4
this.$router.push({
	path:'/B',
	query:{c:3,d:4} 
})

接收数据代码如下

this.$route.query.c,
this.$route.query.d

data

vue实例中data使用return包裹
https://blog.csdn.net/fengjingyu168/article/details/72900624

为何在大型项目中data需要使用return返回数据呢?

  • 不使用return包裹的数据会在项目的全局可见,会造成变量污染
  • 使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件。

:style

:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼
峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
【前端】Vue学习笔记_第4张图片

  • 使用 { } 动态绑定style会导致模板结构臃肿的问题。此时可以使用对象语法进行简化

:class

class 可以与 :class 共存
  • 可以通过三元表达式,动态的为元素绑定 class 的类名。示例代码如下:

【前端】Vue学习笔记_第5张图片

  • 绑定一个类名
:class="{'active':true}"
  • 如果元素需要动态绑定多个 class 的类名,此时可以使用数组的语法格式:
    【前端】Vue学习笔记_第6张图片
  • 使用数组语法动态绑定 class 会导致模板结构臃肿的问题。此时可以使用对象语法进行简化:
    【前端】Vue学习笔记_第7张图片

监听器

  data(){
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: {
    // 如果 `question` 发生改变,这个函数就会运行 
    // 参数:新值,旧值(非必须)
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.debouncedGetAnswer()
    }
  },
  

immediate 选项

默认情况下,组件在初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项。实例代码如下:
【前端】Vue学习笔记_第8张图片

deep 选项

当 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项,代码示例如下:
(对象中的任意一个属性值发生了变化都会触发)
【前端】Vue学习笔记_第9张图片

监听对象单个属性的变化

【前端】Vue学习笔记_第10张图片

区别

【前端】Vue学习笔记_第11张图片

生命周期

【前端】Vue学习笔记_第12张图片

beforeCreate 实例创建前
created 实例创建完毕之后
beforeMount 实例渲染前(挂载)(此时无法找到任何模版DOM节点)
mounted 实例渲染完毕之后(挂载)
beforeUpdate 实例更新前
updated 实例更新完毕之后
beforeDestroy 实例销毁前
destroyed 实例销毁完毕

【前端】Vue学习笔记_第13张图片

组件的生命周期函数

来源:https://segmentfault.com/a/1190000011381906

  • created:html加载完成之前,执行。执行顺序:父组件-子组件
  • mounted:html加载完成后执行。执行顺序:子组件-父组件
  • methods:事件方法执行
  • watch:watch是去监听一个值的变化,然后执行相对应的函数。
  • computed:computed是计算属性,也就是依赖其它的属性计算所得出最后的值

对象里面的函数

	methods: {
            add: function () {
                console.log("add")
                this.counter++
            },
            // ES6 语法
            sub() {
                console.log("sub")
                this.counter--
            }
        }

父子组件

父组件与子组件其实是一个相对的概念,你可以把它理解包含与被包含的关系,被包含的自定义标签元素称为子组件,根实例下的模板的内容是父组件,可以对比以前写html的时候,元素嵌套那种层级关系。

而通过全局注册(Vue.component(tagName, options))或者局部注册,自定义标签元素的是子组件,在根实例的作用域范围内,父实例的模块中以自定义元素 调用子组件进行使用,要注意的是确保在初始化根实例之前,注册了子组件

兄弟组件:同级关系的自定义标签元素在父模板中进行使用称为为兄弟组件
来源:https://www.jianshu.com/p/af9cb05bfbaf

简单的父子组件传值
https://www.cnblogs.com/phermis/p/10710894.html

父 -> 子
【前端】Vue学习笔记_第14张图片

子 -> 父
【前端】Vue学习笔记_第15张图片

父 <-> 子
【前端】Vue学习笔记_第16张图片

prop 属性 双向绑定

https://www.cnblogs.com/leslie1943/p/13359456.html
https://www.cnblogs.com/lhuser/p/11269546.html

v-bind只能实现单向绑定
v-model(v-bind+触发的input事件)实现双向绑定

  • 方法一
    【前端】Vue学习笔记_第17张图片
  • 方法二
    .sync 修饰符
    官方文档:https://cn.vuejs.org/v2/guide/components-custom-events.html#sync-%E4%BF%AE%E9%A5%B0%E7%AC%A6

props

props中的属性都是只读的,千万不要用v-model绑定props属性
正确的做法:将 props 的初始值转存到 data 中,因为 data 中的数据是可读可写的!用v-model绑定data属性

在 JavaScript 中对象数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。

兄弟组件之间数据共享

https://www.bilibili.com/video/BV1zq4y1p7ga?p=415

兄弟组件之间实现数据共享的方案是EventBus。可以借助于第三方的包 mitt 来创建 eventBus 对象,从而实现兄弟组件之间的数据共享。示意图如下

【前端】Vue学习笔记_第18张图片
下载
3.2 创建公共的 EventBus 模块
在项目中创建公共的 eventBus 模块如下:
【前端】Vue学习笔记_第19张图片
3.3 在数据接收方自定义事件
在数据接收方,调用 bus.on(‘事件名称’, 事件处理函数) 方法注册一个自定义事件。示例代码如下:
注意: 一定要写在created函数内
【前端】Vue学习笔记_第20张图片
3.4 在数据接发送方触发事件
在数据发送方,调用 bus.emit(‘事件名称’, 要发送的数据) 方法触发自定义事件。示例代码如下:
注意: 一定要写在created函数内
【前端】Vue学习笔记_第21张图片

后代关系组件之间的数据共享

https://www.bilibili.com/video/BV1zq4y1p7ga?p=417

后代关系组件之间共享数据,指的是父节点的组件向其子孙组件共享数据。此时组件之间的嵌套关系比较复杂,
可以使用 provide 和 inject 实现后代关系组件之间的数据共享。
provide 提供数据
inject 接受数据

4.1 父节点通过 provide 共享数据
父节点的组件可以通过provide 方法,对其子孙组件共享数据:
【前端】Vue学习笔记_第22张图片
4.2 子孙节点通过 inject 接收数据
子孙节点可以使用 inject 数组,接收父级节点向下共享的数据。示例代码如下:
【前端】Vue学习笔记_第23张图片
4.3 父节点对外共享响应式的数据
父节点使用 provide 向下共享数据时,可以结合computed函数向下共享响应式的数据。示例代码如下:
【前端】Vue学习笔记_第24张图片
4.4 子孙节点使用响应式的数据
如果父级节点共享的是响应式的数据,则子孙节点必须以.value 的形式进行使用。示例代码如下:
【前端】Vue学习笔记_第25张图片

element ui

:router="true"可以简写为router
ref 相当于取别名 一般命名为:xxxRef

静态html中使用vue.js

不建议使用.vue 文件

请求可以使用 jquery、axios(推荐)

最好自己在request.js 封装一下 请求的方法和格式

index.html

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>indextitle>
    <script src="js/jquery-3.5.1.js">script>
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
  head>
  <body>
    <div id="app">
      <div style="background: red">{{ name }}div>
    div>
  body>
  <script src="js/request.js">script>
  <script>
    var app = new Vue({
      el: "#app",
      data: { // 这里最好写上所有需要的参数
        name: "123",
      },
      created() {
        this.getName();
      },
      methods: {
        getName() {
          this.name = sendGet();
        },
      },
    });

	app.getName(); // 调用vue中的方法
  script>
html>

request.js

/*
 静态项目不能这样引入外部js插件,如jquery、axios、qs等等,因为这些插件没有导出
The requested module '../js/jquery.js' does not provide an export named 'default'
需要在每个html中使用引入
import $ from "/js/jquery.js";
*/

/*
js/my.js

let obj = {
  click: function () {
    console.log("click me");
  },
  name: "jane",
};
export { obj };

自定义js有导出的可以
import obj from 'js/my.js'
*/

// 模拟返回服务器数据
function sendGet() {
  return "江帆啊";
}

抽离组件

不建议这样,建议直接使用vue重构

进阶

component 动态组件

【前端】Vue学习笔记_第26张图片

【前端】Vue学习笔记_第27张图片

keep-alive

【前端】Vue学习笔记_第28张图片

插槽

具名插槽

  • 缩写 v-slot:header , #header

默认有一个v-slot:default / #default

作用域插槽

infomation对象赋值给info变量,然后scope获取到 info对象并把其作为一个值
scope:{
info:{…}
}

App.vue输出:info{…}

info,scope名称不唯一
【前端】Vue学习笔记_第29张图片

解构

传递多个对象

// ElementUI 的 表格经常用到
<el-table-column label="ID">
        <template slot-scope="{ row }">
          <span>{{ row }}</span>
        </template>
</el-table-column>

// 常规
v-slot:default="scope"
{{scope.msg}}
{{scope.infomation.address}}

【前端】Vue学习笔记_第30张图片

自定义指令

vue2:https://cn.vuejs.org/v2/guide/custom-directive.html
insert update -> mounted updated
vue3:https://vue3js.cn/docs/zh/guide/custom-directive.html

二者钩子函数不一样

    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.js">script>

    <div id="app">
      <input type="text" v-focus />
    div>
  
  <script>
    let app = new Vue({
      el: "#app",
      data: {},
      directives: {
        focus: {
          inserted(el) { // vue3为 mounted
            el.focus();
          },
        },
      },
    });
  script>


  • vue3

【前端】Vue学习笔记_第31张图片
【前端】Vue学习笔记_第32张图片

传递参数

【前端】Vue学习笔记_第33张图片

你可能感兴趣的:(前端,vue,vue)