【Vue学习笔记】

初始化vue项目

确保node版本是v15以上,推荐nvm管理node版本。

npm install vite@latest

基础语法

属性绑定

v-bind:或者简写:

<template>
  <button v-bind:disabled="state">按钮</button>
  <button :disabled="state">按钮</button>
 </template>
<script>
	export default {
	  components: {VIfDemoComponent},
	  data() {
	    return {
	      msg: "模板",
	      state: false
	    }
	  }
	}
</script>
条件渲染

v-if, v-else-if, v-else, v-show 用于标签内部

<template>
  <h3 v-if="type === 'a'">a</h3>
  <h3 v-else-if="type === 'b'">b</h3>
  <h3 v-else-if="type === 'c'">c</h3>
  <h3 v-else>not abc</h3>

  <h3 v-show="show === true">show true</h3>
</template>

<script>
export default {
  name: "VIfDemoComponent",
  data() {
    return {
      type: 'a',
      show: true
    }
  }
}
</script>
列表渲染
  1. v-for指令基于一个数组来渲染列表。 v-for有第二个参数index,数组的下标
<template>
  <h3>列表渲染</h3>
  <ul>
    <li v-for="(film, index) in films">{{ film }}</li>
  </ul>
</template>

<script>
export default {
  name: "VForDemoComponent",
  data() {
    return {
      films: ['钢铁侠', '变形金刚', '绿巨人']
    }
  }
}
</script>
  1. v-for也可以遍历对象的所有属性
    参数顺序是固定的
    第一个参数value是属性值
    第二个参数key是属性键
    第三个参数index是索引
  <p v-for="(value, key, index) of book">{{value}}-{{key}}-{{index}}</p>
通过key管理状态

Vue默认采用“就地更新”的策略来更新通过v-for渲染的元素,当数据顺序变化时,Vue不会移动元素位置,而是重新渲染。重新渲染影响性能
为v-for渲染的元素添加key属性,会给Vue一个提示,从而在发生顺序变化时重用和重新排序现有的元素。

  <p v-for="(per, index) in result" :key="index">{{per.name}}-的能力是-{{per.ability}}</p>

项目中key的值一般采用数据的id

事件处理

v-on指令或者简写成@ 来监听DOM事件,并在触发时执行对应的js。
内联式和方法式

<template>
  <h3>事件处理</h3>
  <button v-on:click="addCount">加一</button>
  <button @click="count--">减一</button>
  count<p>{{count}}</p>
</template>

<script>
export default {
  name: "VOnDemoComponent",
  data() {
    return {
      count: 0
    }
  },
  methods: {
    addCount() {
      this.count++
    }
  }
}
</script>
事件参数

只有event参数时可以直接获取。如果有自定义参数,用**$event**传递event参数

<template>
  <h3>事件传参</h3>
  <button @click="eventHandler">传递event</button>
  <button @click="paramAndEventHandler('自定义参数', $event)">传递自定义参数和event</button>
</template>

<script>
export default {
  name: "EventDemoComponent",
  methods: {
    eventHandler(e) {
      console.log(e)
    },
    paramAndEventHandler(param, e) {
      console.log(param)
      console.log(e)
    }
  }
}
</script>
常见事件修饰符

阻止默认事件@click.prevent
阻止事件冒泡@click.stop

数组变化侦测
  • 变更方法​
    Vue 能够侦听响应式数组的变更方法,并在它们被调用时触发相关的更新。这些变更方法包括:
    push()
    pop()
    shift()
    unshift()
    splice()
    sort()
    reverse()
  • 替换一个数组
    变更方法,顾名思义,就是会对调用它们的原数组进行变更。相对地,也有一些不可变 (immutable) 方法,例如 filter(),concat() 和 slice(),这些都不会更改原数组,而总是返回一个新数组。当遇到的是非变更方法时,我们需要将旧的数组替换为新的
    this.items = this.items.filter((item) => item.message.match(/Foo/))
计算属性

将复杂的计算逻辑从模板中提取到计算属性中。
与方法相比,计算属性会基于其响应式依赖被缓存,只要依赖不变,计算属性只会执行一次。

<template>
  <h3>计算属性</h3>
  <p>是否有出版的书籍:{{ownedBooks}}</p>
</template>

<script>
export default {
  name: "ComputedDemo",
  data() {
    return {
      author: {
        name: 'Doe',
        books: ['Vue2','Vue3','Vue4']
      }
    }
  },
  computed: {
    ownedBooks() {
      return this.author.books.length > 0 ? 'yes' : 'no'
    }
  }
}
</script>
Class绑定
  • 绑定对象
  • 绑定数组
  • 数组嵌套对象
    因为 class 和 style 都是 attribute,我们可以和其他 attribute 一样使用 v-bind 将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。因此,Vue 专门为 class 和 style 的 v-bind 用法提供了特殊的功能增强
<template>
  <h3>class绑定</h3>
  <h3>0. 内联样式</h3>
  <p :class="{'active': isActive, 'text-danger': hasError}">测试</p>
  <h3>1. 绑定对象</h3>
  <p :class="classObj">测试</p>
  <h3>2. 绑定数组</h3>
  <p :class="classArr">测试</p>
  <h3>3. 数组嵌套对象</h3>
  <p :class="['active', {'text-danger': hasError}]">测试</p>
</template>

<script>
export default {
  name: "ClassDemo",
  data() {
    return {
      isActive: true,
      hasError: true,
      classObj: {
        'active': true,
        'text-danger': true,
      },
      classArr: ['active', 'text-danger']
    }
  }
}
</script>

<style scoped>
 .active {
   font-size: 30px;
 }
 .text-danger {
   background-color: red;
 }
</style>

总结:绑定对象更适合于动态样式,绑定数组写起来更容易,只需要把需要的样式放进数组。数组嵌套对象和对象嵌套数组都可以,这里只展示了数组嵌套对象。

style绑定

和class绑定类似,也有内联样式,绑定对象,绑定数组。绑定包含多个样式对象的数组时,这些对象会合并渲染到同一元素上。

<template>
  <h3>style绑定</h3>
  <p :style="styleObj">style绑定对象</p>
  <p :style="[styleObj, styleObj2]">style绑定数组</p>
</template>

<script>
export default {
  name: "StyleDemo",
  data() {
    return {
      styleObj: {
        color: 'red',
        fontWeight: 'bold'
      },
      styleObj2: {
        fontSize: '30px'
      }
    }
  }
}
</script>
侦听器

watch
注意点:侦听器函数的函数名必须和侦听的属性名一致,有两个参数,第一个是新值,第二个原始值。

<template>
  <h3>侦听器</h3>
  <p>{{msg}}</p>
  <button @click="this.msg = 'World'">修改</button>
</template>

<script>
export default {
  name: "WatchDemo",
  data() {
    return {
      msg: 'Hello'
    }
  },
  watch: {
    msg(newVal, oldVal) {
      console.log('初始值是'+oldVal+',新值是'+newVal)
    }
  }
}
</script>
表单输入绑定

v-model
修饰符:.lazy,.number, .trim

<template>
  <h3>表单输入绑定</h3>
  <p>message is: {{ msg }}</p>
  <input v-model="msg" />
</template>

<script>
export default {
  name: "VModelDemo",
  data() {
    return {
      msg: ''
    }
  }
}
</script>
模板引用

其作用就是操作DOM元素。
挂载结束后引用都会被暴露在 this.$refs 之上。

<template>
  <p>模板引用</p>
  <p ref="xxx">初始p标签</p>
  <button @click="getPMsg">获取p标签内容</button>
</template>

<script>
export default {
  name: "RefDemo",
  methods: {
    getPMsg() {
      console.log(this.$refs.xxx.innerText)
    }
  }
}
</script>

组件

全局组件注册

在main.js中注册主键可以用于全局。

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import BaseUserComponent from './components/BaseUserComponent.vue'

const app = createApp(App);

app.component("BaseUserComponent", BaseUserComponent)

app.mount('#app');
组件传值props(父传子)

子组件用props中定义的属性接收父组件传递的参数。
父组件中可以属性绑定,传递动态的参数。
props可以接收任何类型。
props是只读的,不可修改。

子组件:
<template>
  <div>子组件内容开始</div>
  <div>
    {{msg}}-{{msg2}}
  </div>
  <div>子组件内容结束</div>
</template>

<script>
export default {
  name: "Child",
  props: ['msg', 'msg2']
}
</script>
-------------------------------------
父组件:
<template>
  <h3>父组件</h3>
  <Child msg="消息1" :msg2="msg2"></Child>
</template>

<script>
import Child from "./Child.vue";
export default {
  name: "Parent",
  components: {Child},
  data() {
    return {
      msg2: '消息2'
    }
  }
}
</script>
  • props的校验,默认值,required
    如果类型是数组和对象,默认值需要以函数形式返回
<script>
export default {
  name: "Child",
  props: {
    msg: {
      type: String,
      default: '初始msg',
      required: true
    },
    msg1: {
      type: String
    },
    names: {
      type: Array,
      default() {
        return ['Ann','Bob']
      }
    }
  }
}
</script>
组件传值(子传父)

**1. this. e m i t ( ′ 自定义事件 名 ′ , ′ 需要传递的参 数 ′ ) 2. p r o p s 也能实现子传父 ∗ ∗ 子组件中通过 t h i s . emit('自定义事件名', '需要传递的参数') 2. props也能实现子传父** 子组件中通过this. emit(自定义事件,需要传递的参)2.props也能实现子传父子组件中通过this.emit自定义事件名,父组件中使用该事件触点相应业务方法。
props实现子传父,更确切的说应该是父传子再传父。父元素传给子元素一个方法,子元素中调用该方法时携带参数,实现子传父。

子组件
<template>
  <button @click="msg2Parent">传递数据</button>
</template>

<script>
export default {
  name: "BComponent",
  data() {
    return {
      childMsg: '子组件数据'
    }
  },
  methods: {
    msg2Parent() {
      this.$emit("transferEvent", this.childMsg);
    }
  }
}
</script>
----------------------------------------
<template>
  <BComponent @transferEvent="getData"></BComponent>
  {{msg}}
</template>

<script>
import BComponent from "./BComponent.vue";
export default {
  name: "AComponent",
  components: {BComponent},
  data() {
    return {
      msg: ''
    }
  },
  methods: {
    getData(data) {
      this.msg = data
    }
  }
}
</script>
  • 通过props接收函数的形式实现子传父
子元素:
<template>
  <h3>BBcomponent</h3>
  <p>{{ myEvent('子组件数据') }}</p>
</template>

<script>
export default {
  name: "BBComponent",
  props: {
    myEvent: Function
  }
}
</script>
------------------------------------------
<template>
  <h3>AAcomponent</h3>
  <BBComponent :myEvent="getData"></BBComponent>
  <p>来自子组件的数据:{{msg}}</p>
</template>

<script>
import BBComponent from "./BBComponent.vue";
export default {
  name: "AAComponent",
  components: {BBComponent},
  data() {
    return {
      msg: ''
    }
  },
  methods: {
    getData(data) {
      this.msg = data
    }
  }
}
</script>
插槽slot

插槽的作用是将父组件的标签片段传入子组件中显示,子组件可以通过slot元素决定显示位置。
slot元素是一个插槽出口,标示了父元素提供的插槽内容在哪里被渲染。

子组件:
<template>
  <p>这是子组件</p>
  <slot></slot>
</template>
-----------------------------------------------
父组件:
<template>
  <h3>这是父组件</h3>
  <BaseSlot>
    <div>这是父组件传递给子组件的内容</div>
  </BaseSlot>
</template>
  • 渲染作用域
    父组件中定义插槽内容
    插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模板中定义的。
  • 插槽默认值
    子组件中定义插槽默认值
    <slot>插槽默认值</slot>
  • 具名插槽
    v-slot命令可以简写为#
    父组件中用templete标签包裹元素,templete标签中用v-slot指定插槽名。
    子组件中在slot标签用name属性指定插槽名。
    在这里插入图片描述
子组件:
<template>
  <slot name="slot1"></slot>
  <p>这是子组件</p>
  <slot name="slot2"></slot>
</template>
-------------------------------------
父组件:
<template>
  <h3>这是父组件</h3>
  <BaseSlot>
    <template v-slot:slot1>
      <div>这是slot1</div>
    </template>
    <template #slot2>
      <div>这是slot2</div>
    </template>
  </BaseSlot>
</template>
  • 插槽数据传递
    子组件数据传递到父组件插槽内容中需要区分两种情况。
  1. 普通插槽
    子组件定义参数,在slot标签中定义参数属性。
    父组件中,在子组件内用v-slot=‘xxx’的方式接受所有子组件的数据。
  2. 具名插槽
    子组件中通普通插槽。
    父组件中,在每个templete件标签内用#aaa='xxx’的方式接受所有子组件的数据。
子组件:
<template>
  <slot name="slot1" :msg1="msg1"></slot>
  <p>这是子组件</p>
  <slot name="slot2" :msg2="msg2"></slot>
</template>

<script>
export default {
  name: "BaseSlot",
  data() {
    return {
      msg1: '子组件数据1',
      msg2: '子组件数据2',
    }
  }
}
</script>
-------------------------------------
父组件:
<template>
  <h3>这是父组件</h3>
  <BaseSlot>
    <template v-slot:slot1="obj">
      <div>这是slot1 - {{obj.msg1}}</div>
    </template>
    <template #slot2="obj">
      <div>这是slot2 - {{obj.msg2}}</div>
    </template>
  </BaseSlot>
</template>
组件的生命周期

在这里插入图片描述
可以用ref测试生命周期。只有渲染完成后this.$ref才能获取到DOM元素。

组件切换

Vue提供了component标签用于承载组件,通过is属性确定展示哪一个组件。
注意点:由于用的是字符串指定的组件,编译期不会自动导入组件,
需要手动把组件导入进来。

<template>
  <component :is="switchComponent"></component>
  <button @click="changeC">切换</button>
</template>

<script>
import ComponentA from "./ComponentA.vue";
import ComponentB from "./ComponentB.vue";
export default {
  name: "isComponent",
  components: {ComponentA,ComponentB},
  data() {
    return {
      switchComponent: 'ComponentA'
    }
  },
  methods:{
    changeC(){
      this.switchComponent=this.switchComponent==='ComponentA'?'ComponentB':'ComponentA'
    }
  }
}
</script>
组件保持存活

<keep-alive></keep-alive>包裹需要保持存活的片段,这样组件就不会进入卸载阶段。

异步组件

defineAsyncComponent

import {defineAsyncComponent} from "vue";
const ComponentB = defineAsyncComponent(() => {
  import("./ComponentB.vue")
})
Provide & Inject

多级组件实现数据传递可以使用Prop 逐级透传,但是比较麻烦。
Vue提供了Provide & Inject的方式可以方便的实现。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

先祖组件:
<template>
  <Inject1Component></Inject1Component>
</template>

<script>
import Inject1Component from "./Inject1Component.vue";
export default {
  name: "ProviderComponent",
  components: {Inject1Component},
  data() {
    return {
      msg: '祖先数据'
    }
  },
  provide() {
    return {
      msg: this.msg
    }
  }
}
</script>
-------------------------------------------
父组件:
<template>
  <Inject2Component></Inject2Component>
  <p>儿子组件获取祖先的数据:{{ inject1Msg }}</p>
</template>

<script>
import Inject2Component from "./Inject2Component.vue";
export default {
  name: "Inject1Component",
  components: {Inject2Component},
  inject: ['msg'],
  data() {
    return {
      inject1Msg: this.msg
    }
  }

}
</script>
-------------------------------------------
子组件:
<template>
  <p>孙子组件获取祖先数据:{{inject2Msg}}</p>
</template>

<script>
export default {
  name: "Inject2Component",
  inject: ['msg'],
  data() {
    return {
      inject2Msg: this.msg
    }
  }
}
</script>
  • 全局provide
    在main.js中定义全局可获取的数据,其他组件还是一样通过inject获取。
    app.provide('globalData', '这是全局数据')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值