Vue2 - 基本用法

67 阅读5分钟

v-if,v-show

  • v-show 都会渲染,通过display:none控制显示/隐藏 -- 适合频繁切换使用
  • v-if 不符合直接不渲染,更高的切换开销,切换时子组件会销毁重建 -- 渲染后很少改变使用

事件修饰符

执行事件时进行了一些封装

  1. @keyup.enter="fn" 回车键执行
相当于
fn(){
   if(e.key === 'Enter'){
      执行内容...
   }
}
  1. .prevent阻止默认事件 .stop阻止冒泡 @click.prevent="clickHandle"
  2. v-model.trim

数组变化监听

  • 调用可以改变原数组的方法,会实时更新数据
  • push, pop, shift, unshift, splice, sort, reverse
this.data.push(...)
  • 其他方法则需要重新赋值
this.data = this.data.concact(...)

计算属性

基于现有数据,计算出来的新属性,依赖数据变化,自动重新计算

computed: {
    itContent() {
      return this.data.content.length > 0 ? "ya" : "nu";
      必须return一个结果
    },
  },     

使用 {{ itContent }}--本质还是属性,不需要加括号

计算属性 对比 方法

定义函数方法也可以实现类似功能,

  • 计算属性 缓存特性--依赖值不变时,只会执行一次,页面多个地方使用计算属性,也只会执行一次
  • methods方法 则是调用一次就会执行一次,无论依赖值是否改变

计算属性修改

  • 获取值 {{ fullname }},执行get中的内容
  • 修改值 this.fullname = ...,执行set中的内容
 computed: {
    fullname: {
      get() {
        return this.firstName + this.lastName;
      },
      set(value) {
        this.firstName = value.slice(0, 1);
        this.lastName = value.slice(1);
      },
    },
  },

class样式绑定

可以接受数组/对象

<h3 :class="classObject">class样式绑定</h3>
<h3 :class="[arrActive, arrDanger]"></h3>
data(){
   return{
      classObject: {
        active: true,
        danger: true,
      },
      arrActive: active
      arrDanger: danger
   }
}

组件样式 scoped

< style scoped>,样式只作用于当前组件

  • 原理,标签加上 data-v-hash的属性,css选择器也会被添加[data-v-hash]的属性选择器

watch 监听器

监听到数据变化的过程,

  • 数据发生变化,自动执行的函数
  • 函数名和监听的数据对象名一致
  1. 简单类型数据
  <p>{{ message }}</p> 
----------
export default {
  data() {
    return {
      message: "hello",  数据
    };
  },
  watch: {  监听
    message(newValue, oldValue) {
      console.log("oldvalue:", oldValue, "--newvalue", newValue);
    },
  },
};      
  1. 深度监听 立即执行
data(){
   return{
     obj:{ words:'', lang:'' }
   }
}
watch:{
   obj:{
      deep: true,  // 复杂类型
      immediate: true, //立即执行一次
      handler(newValue){}
   }
}

表单输入绑定 v-model

表单的数据可以实时获取到

 <form>
    <input v-model="message" type="text" />
  </form>
  <p>{{ message }}</p>
  
  data() {
    return {
      message: "",
    };
  },
  • v-model.lazy惰性,不实时,失焦/回车才获取数据
  • v-model.trim, v-model.number

直接访问底层DOM - ref

vue抽象了大部分操作

  • 内容 {{}},属性v-bind: , 事件@
  • 查找范围,当前组件
 <h3 ref="container">容器</h3>
  <button @click="getElement">获取元素</button>
  
  methods: {
    getElement() {
      console.log(this.$refs.container); 打印<h3>hahahah</h3>
      this.$refs.container.innerHTML = "hahahah";
    },
  },

组件引入方式

  1. 局部注册 - 某个组件内部引入显示
<script>
import FormDemo from "./components/FormDemo.vue";  --1.引入组件
export default {               --2.注入组件
  components: { FormDemo },
};
</script>
<template>
  <FormDemo />                --3.显示组件
</template>
---------------------
<script setup> 设置了setup可以省略第2步
  1. 全局注册 - 最外层注册一次,哪里都可以引入

image.png

  • 不方便打包,无法自动移除

组件传递数据 - 父传子

  • props可以接受任何类型数据 父组件
 <Child title="props title" :info="message" />
 -------info为动态值
  data() {
    return {
      message: "动态传递数据",
    };
  },

子组件

export default {
  data() {
    return;
  },
  props: ["title", "message"],
};

props校验

类型,默认值,必传标识

  props: {
    title: {  接受传入props title
      type: [String, Number], ----类型限制
      default: "aaa",  ----默认值
      required: true,
      validator(value){ //自定义校验
        if(){ return true }
        else{ return false  }
      }
    },
  },

自定义事件 - 子传父

子组件可以调用父组件的事件 父组件

 <Child @someEvent="getHandle" />
 --------------------
  methods: {
    getHandle(data) {
      this.message = data;
    },
  },

子组件

 <button @click="clickEvent">传递数据</button>
------------------------------
  methods: {
    clickEvent() {
      this.$emit("someEvent", "child数据");
      -- someEvent定义在子组件上的事件
    },
  },

v-model原理

v-model是一个语法糖,input上就是value属性和input事件合写

<input v-model="msg" />
<input :value="msg" @input="msg = $event.target.value" />

v-model表单组件类封装

<InputCom v-model="text" />
// <InputCom :value="text" @input="text=$event.target.value" />
-------
<input :value="value" @change="handleChange" />
export default{
  props:['value'],
  methods:{
    handleChange(e){
      this.$emit('input', e.target.value)
    }
  }
}

自定义指令

自定义指令,封装dom操作

元素加载自动获得焦点
mounted(){
  this.$refs.inp.focus()
}
--------------
directives:{
  'focus':{
     inserted(el){  inserted: 指令所在元素插入到页面中时触发;el:指令绑定的元素
        el.focus()
     }
  }
}
<input v-focus>

组件自定义事件和v-model

v-model可以实时获取到form表单输入的内容,现在想在另一个组件中显示对应的内容

  • 表单组件
<input type="text" v-model="search" /> ----input输入框
<script>
export default {
  data() {
    return {
      search: "",
    };
  },
  watch: {  -------状态修改监听
    search(newValue, oldValue) {
      this.$emit("searchEvent", newValue); ----调用组件自定义事件啊
    },
  },
};
</script>
  • 获取输入内容的组件
<Search @searchEvent="handleS" />
export default {
  data() {
    return {
      message: "",
    };
  },
  methods: {
    handleS(data) {
      this.message = data;
    },
  },
};
</script>

插槽

组件内的结构,支持自定义

  1. < slot>元素,是一个插槽出口,表示父元素提供的内容在哪里渲染
  2. 插槽内容可以访问到父组件的作用域,因为插槽内容本身在父组件中定义
  3. 具名插槽 - 父元素渲染多块内容在子元素中 父元素:template v-slot:Header / #Header分别标识不同内容
<template>
  <SlotsBase>
    <template v-slot:Header> -------第一块内容
    <div>
      <h3>插槽标题</h3>
    </div>
    </template>
    <template #main>  ---------第二块内容
      <div>
        <h3>插槽内容</h3>
      </div>
    </template>
  </SlotsBase>
</template>

子元素

<template>
  <slot name="Header"></slot>  ---引用展示
  <hr />
  <slot name="main"></slot>
</template>
  1. 插槽传值 - 使用子元素的值 子元素传值
<slot :msg="message"></slot>

父元素获取

<SlotsBase v-slot="slotProps"> ---子组件上添加v-slot属性
{{ slotProps.msg }}

具名插槽传值

 <template>
  <SlotsBase>
    <template #Header="slotProps"> -------对应模板上添加
    <div>
      <h3>插槽标题</h3>
    </div>
    </template>
  </SlotsBase>
</template>

生命周期

生命周期函数,自动执行

  1. 创建期 beforeCreate created --组件创建完成,但还没有显示
  2. 挂载期 beforeMount mounted
  3. 更新期 beforeUpdate updated
  4. 销毁期 beforeUnmount unMounted

应用

  1. ref获取DOM结构 mounted(){ 挂载后获取 }
  2. created() 可以发送初始化渲染请求,可以this.数据 = ...
  3. mounted(){ 页面结构已加载,可以操作dom (请求获取数据)}

动态组件

两个组件切换展示

<component :is="tabCom"></component>
--------------
data(){
  return{
    tabCom:'ComponentA' --赋值为字符串形式,引入的组件名称
  }
},
methods:{
   change(){
      this.tabCom = this.tabCom == 'ComponentA' ? 'ComponentB' : 'ComponentA'
   }
}

组件保持存活

< keep-alive>包裹组件< /keep-alive>

异步组件

在需要展示的时候才加载

const ComB = defineAsyncComponent(() => import("./components/ComB.vue"));

跨层级传递数据

根组件向嵌套多层的子组件传递数据,不需props层层传递

  • provide inject
------根组件
provide(){
   return {
      message: this.message
   }
}
------子组件
inject:["message"]

Vue从哪里开始

  • 一个vue项目中,有且只有一个vue的实例对象
  • 传入createApp()的参数是一个组件,“根组件”
import { createApp } from 'vue'
import App from './App.vue'
 
const app = createApp(App); ---app: vue的实例对象
app.mount('#app')