Web前端:Vue3.js摘要

一、基本语法:
1.文件结构说明:
(1)App.vue(主vue,其他.vue组件文件一样的结构):
<template>   //1.vue模版部分,使用html标签实现页面布局
  <html标签>...<html标签>
  ...
</template>
<script>      //2.vue代码部分,定义vue属性、计算属性、函数、组件等
export default {
  name: 'App',  //当前vue名称
  ..
}
</script>
<style>      //3.样式部分,编写CSS样式
  ...
</style>

(2)main.js(主JS,入口):
import { createApp } from 'vue'    //导入vue的createApp系统函数
import App from './App.vue'       //导入上面的App.vue
const app = createApp(App)      //创建vue应用,
app.mount('#app')               //挂载到根节点上

2.属性(类似Java变量):
(1)普通属性:
方式一,选项式定义属性:
<script>
export default {
  data() { //定义属性列表,在vue中使用this.属性名,在html标签中使用:{{ 属性名 }}
    return {
      属性名: '值',          //使用:{{ 属性名 }}
      列表属性名: ['值1', '值2'],     //使用:{{ 列表属性名[下标] }}
      对象属性名: {字段1: '值', 字段2: 值},  //使用:{{ 对象属性名.字段1 }}
    }
  },
}
</script>
方式二,组合式定义属性:
<script setup>
import { ref, reactive } from 'vue'  //导入ref与reactive
const 属性名 = ref('值') //ref适用基础类型,使用:{{ 属性名 }}
const 列表属性名 = reactive(['值1', '值2'])  //reactive适用列表或对象类型,使用:{{ 列表属性名[下标] }}
const 对象属性名 = reactive({字段1: '值', 字段2: '值'}) //使用:{{ 对象属性名.字段1 }}
</script>
使用属性:
<template>
  {{ 属性名 }} {{ 列表属性名[下标] }} {{ 对象属性名.字段1 }}
</template>

(2)计算属性(computed):
方式一,选项式定义计算属性:
<script>
export default {
  computed: { //定义计算属性列表
//计算属性名: function(){ //等同下面简写
    计算属性名(){ //名称自定义
      return 属性名 + 10;  //当表达式中属性值变化时才会重新计算
    },
  },
}
</script>
方式二,组合式定义计算属性:
<script setup>
import { ref, computed } from 'vue'  //导入computed
const 属性名 = ref(原数值)
const 计算属性名 = computed(() => {  //只含get方法时用此实现方式
  return 属性名.value + 10  //当表达式中属性值变化时才会重新计算
})
const 计算属性名2 = computed({  //含get/set方法时用此实现方式
  get() {
    return 属性名.value + 10  //当表达式中属性值变化时才会重新计算
  },
  set(newValue) {
    属性名.value = newValue
  }
})
</script>

(3)监听属性(watch):
方式一,选项式定义监听属性:
<script>
export default {
  watch: { //定义需要被监听值改变的属性列表,当属性值改变时触发
//属性名: function(){  //等同下面简写
    属性名(newValue, oldValue){ //属性名为data中定义的属性,参数为旧值,改变后的新值
      //此处编写属性值改变后的逻辑
    },
  },
}
</script>
方式二,组合式定义监听属性watch:
说明:不加immediate:true配置时,只有属性值改变时才触发监听
<script setup>
import { ref, reactive, watch } from 'vue'  //导入watch
const 属性名 = ref(0)
const 对象属性名 = reactive({ 属性1: 0 })
watch(属性名, (newValue, oldValue) => {  //监听基本类型属性,值改变时触发
  //...
}, { immediate: false, once: false })  //immediate:true表示监听器创建时立刻触发监听,  once:true表示当属性值变化时仅触发一次
watch(() => 对象属性名.属性1, (newValue, oldValue) => { //监听对象类型属性,值改变时触发
  //...
})
watch([属性名1, 属性名2 ], ([newValue1, newValue2]) => { //监听属性列表
  //...
})
</script>
方式三,组合式定义监听属性watchEffect:
说明:监听器创建时立刻触发监听,且属性值改变时触发监听
<script setup>
import { ref, reactive, watchEffect } from 'vue'  //导入watchEffect
const 属性名 = ref(0)
const 对象属性名 = reactive({ 属性1: 0 })
watchEffect(() => { //不需要监听指定属性
  console.log(属性名.value + " " + 对象属性名.属性1) //会自动监听使用到的属性值
})
</script>

3.函数:
(1)生命周期函数(vue自带):
方式一,选项式实现生命周期函数:
<script>
export default {
   beforeCreate(){ //实例生成之前执行
   },
   created(){ //实例生成之后执行
   },
   beforeMount(){ //内容显示到页面之前执行
   },
   mounted(){ //内容显示到页面之后执行
   },
   beforeUpdate(){ //data中数据变化,页面更新前执行
   },
   updated(){ //data中数据变化,页面更新后执行
   },
   beforeUnmount(){ //页面失效时执行
   },
   unmounted(){ //页面失效,且dom销毁之后执行
   }
}
</script>
方式二,组合式实现生命周期函数:
<script setup>
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'
onBeforeMount(() => { //内容显示到页面之前执行
})
onMounted(() => { //内容显示到页面之后执行
})
onBeforeUpdate(() => { //data中数据变化,页面更新前执行
})
onUpdated(() => { //data中数据变化,页面更新后执行
})
onBeforeUnmount(() => { //页面失效时执行
})
onUnmounted(() => { //页面失效,且dom销毁之后执行
})
</script>

(2)自定义函数:
方式一,选项式定义函数:
<script>
export default {
   methods: { //此处定义函数列表
      函数名(){ //此处的this指向app本身,可以"this.属性名"方式使用属性
         //...代码
      },
      函数名: (param1) => { //箭头函数,此处的this指向window
         //...代码
      }
   }
}
</script>

方式二,组合式定义函数:
<script setup>
function 函数名(){   //定义函数
    //...
}
</script>

使用函数:
<template>
    <div v-on:click="函数名">点击触发函数</div>
</template>

4.指令(v-xxx):
(1)条件语句:
 v-if语句:
<div v-if="vue属性名 或 布尔表达式">...</div>   //vue属性值为true或false
<div v-else-if="vue属性名 或 布尔表达式">...</div>
<div v-else="vue属性名 或 布尔表达式">...</div>
v-show(显示或隐藏):
<div v-show="vue属性名 或 布尔表达式">...</div>   //vue属性值为true或false

(2)v-for(循环语句):
循环列表:
<div v-for="(item, index) in vue列表属性名"  v-bind:key="item">  //index为下标, item为列表中每个值
  当前第{{index}}条的值为 :{{item}}
<div>
循环对象字段:
<div v-for="(value, key, index) in vue对象属性名">  //key为字段名, value为字段值,index为下标
  字段名为{{key}} ,字段值为{{value}}
<div>

(3)v-html(插入html标签):
<div v-html="vue属性名"></div>  //vue属性值为html标签,例<html标签>...</html标签>

(4)v-bind绑定html标签属性(给标签属性赋值):
格式:<html标签 v-bind:标签属性名="vue属性名" /> 
或简写: <html标签 :标签属性名="vue属性名" />
例:
<a v-bind:href="vue属性名">点击跳转</a> //vue属性值为超链接,例http://www.xxx.com 
<1>绑定html标签class属性设置样式:
定义样式:
<style>
   .样式名1 {
      width: 20px; //样式字段列表
      Height: 20px;
   }
   .样式名2 {
      background: red;  //样式字段列表
   }
</style>
定义属性列表:
<script>
export default {
   data() {
      return {
         属性名0: true,     //是否使用指定样式, true使用,false不使用
         属性名1: '样式名1',  //供列表方式使用样式
         属性名2: '样式名2',  //供列表方式使用样式
         对象属性名: {‘样式名1’: true, ‘样式名2’: true},  ///对象方式使用样式
      }
   },
}
</script>
是否使用指定样式:
<div :class="{'样式名1': vue属性名0, '样式名2': vue属性名0}"></div>
列表方式使用样式:
<div :class="[vue属性名1, vue属性名2]"></div>
对象方式使用样式:
<div :class="vue对象属性名"></div>

<2>绑定html标签style属性设置样式:
定义属性列表:
<script>
export default {
   data() {
      return {
         属性名: '20px',  //属性值为样式字段值
         对象属性名1: {width: "20px", height: "20px"},  ///对象字段名为样式字段
 对象属性名2: {color: "red"},  ///供列表方式
      }
   },
}
</script>

属性值为样式字段值:
<div :style="{width: vue属性名}"></div> //width为CSS样式字段宽度
对象字段名为样式字段:
<div :style="vue对象属性名1"></div>
列表方式:
<div :style="[vue对象属性名1, vue对象属性名2]"></div>

(5)v-model双向绑定表单(属性与表单绑定):
修饰符:
v-model.lazy       -将(默认)输入时触发事件 改为 失去焦点时触发事件
v-model.number     -将原值字符串类型转为数值类型
v-model.trim       -去掉首尾空格
使用:
<input type="text" v-model="vue属性名">   //1.单行文本框,显示属性值在文本框中
<input v-model.lazy="vue属性名" >         //单行文本框修饰符使用,可以为lazy、number、trim
<textarea v-model="vue属性名" />          //2.大文本,显示属性值在大文本框中
<input type="radio" value="值1" v-model="vue属性名">       //3.单选框,value值与vue属性值一致时选中此单选框,例vue数据中:data: {vue属性名: '值1']}
<input type="checkbox" value="值1" v-model="vue数组属性名"> //4.复选框,value值在vue数组中时选中此复选框,例vue数据中:data: {vue数组属性名: ['值1', '值2']}
<select v-model="vue属性名">    //5.下拉选择列表(单选),例vue数据中:data: {vue属性名: '值1'}
  <option value="值1">...</option>  //value值与vue属性值一致时选中此item项
  <option value="值2">...</option>
</select>
<select v-model="vue数组属性名" multiple>    //下拉选择列表(多选),例vue数据中:data: {vue数组属性名: ['值1', '值2']}
  <option value="值1">...</option>  //value值与vue属性值一致时选中此item项
  <option value="值2">...</option>  //value值与vue属性值一致时同时选中此item项
</select>

(6)v-on(事件处理):
<div v-on:click="函数名">点击调用函数</div> //函数名也可以换成表达式
或简写方式
<div @click="函数名">点击调用函数</div>
或动态方式,绑定的html标签属性名由vue属性值决定,vue属性值必须是html标签存在的属性名
<div @[vue属性]="..."></div>
事件修饰符:
@click.stop - 阻止冒泡
@click.prevent - 阻止默认事件
@click.capture - 阻止捕获
@click.self - 只监听触发该元素的事件
@click.once - 只触发一次
@click.left - 左键事件
@click.right - 右键事件
@click.middle - 中间滚轮事件
事件修饰符例(阻止表单action事件):
<form action="..." @click.prevent="函数名">...</form>

(7)v-once让标签只渲染一次:
<div v-once>{{vue属性名}}</div>  //首次加载时使用vue属性值,后面vue属性值改变时,此处显示不会变

(8)ref获取DOM节点与组件引用:
在html标签中使用ref传入引用名:
<template>
  <html标签或组件名 ref="引用名">..</html标签或组件名>
</template>
方式一,选项式获取标签的引用:
this.$refs.引用名    //获取html标签或组件标签的引用
方式二,组合式获取标签的引用:
<script setup>
import { ref } from 'vue'
const 标签引用名 = ref(null)  //固定写法:ref(null)
</script>

5.<Teleport>将内容移到指定html标签内:
<template>
  ...
  <Teleport to="html标签名或者标签ID">
    <div>需要移动的内容</div>
  </Teleport>
</template>


二、组件:
1.创建组件文件(放在工程/src/components目录下):
说明:组件是单个文件,例:文件名.vue
实现组件内容:
<template>   //1.vue模版部分,使用html标签实现页面布局
  <html标签>...<html标签>
  ...
</template>
<script>      //2.vue代码部分,定义vue属性、计算属性、函数、组件等
export default {
   name: '单文件组件名',
   //props: ['组件属性名'],  //接收组件标签属性值
   props: { //带有验证的属性
      组件属性名1: String,   //单个类型,属性值必须为此类型
      组件属性名2: [String, Number, Boolean, Array, Object, Date, Function, Symbol],  //多个类型,属性值可以为列表中的任意一种类型
      组件属性名3: {
         type: Object,       //对象类型
         //required: true,     //属性值不能为空
         //default: "默认值",   //基本类型时,设置默认值
         default: function ()  { //对象或数组类型时,设置默认值必须用此方式
            return { 字段名: '值' }  //返回一个对象
         },
         validator: function (value) {  // 自定义验证函数
            return 验证表达式
         }
      }
   },
   inheritAttrs: false,  //false时丢弃传入的属性。默认true,父组件使用子组件时,传入子组件props中未定义的属性时,会将该属性添加到子组件的标签上,子组件有多个标签时传入的属性被丢弃,想要不丢弃得在子组件标签上加v-bind="$attrs",例:<div v-bind="$attrs">...</div>
}
</script>
<!-- 3.样式,scoped限制以下样式只对当前组件生效 -->
<style scoped>
...
</style>

2.注册组件:
(1)注册为全局组件:
说明:main.js中注册组件,在其他vue文件中使用(使用时无需import组件文件)
import { createApp } from 'vue'    //导入vue的createApp系统函数
import App from './App.vue'       //导入App.vue
import 组件名 from './components/组件文件名.vue'   //导入组件文件
const app = createApp(App)      //创建vue应用,
app.component('组件名', 组件名)  //注册为全局组件,任意.vue文件中均可使用此组件
app.mount('#app')               //挂载到根上

(2)注册为局部组件:
说明:在使用组件的vue文件中注册组件+使用
<script>
import 组件名 from './components/组件文件名.vue'  //导入上面的组件文件
export default {
  components: { //定义局部组件列表,仅限当前文件中使用此组件
    组件名,
  }
}
</script>

3.使用注册的组件:
<template>
  <组件名 组件属性名="值"/>  
</template>

4.子组件向父组件通信:
(1)父组件监听事件:
<template>
  <子组件名 @事件名="父函数名"></子组件> <!-- 监听子组件事件(接收子组件数据),触发时调自已的函数,接收参数值并处理 -->
</template>
<script>
import 子组件名 from '@/components/子组件文件名.vue';
export default {
  methods: {
    父函数名(参数名){ //此方法接收子组件触发事件时传入的参数
      //此处处理从子组件接收过来的数据
    }
  },
  components: {
    子组件名
  }
}
</script>

(2)子组件中触发父组件中监听的某个事件并传递数据:
export default {
  emits: ['事件名'], //定义事件列表
  //emits: {       //定义事件列表,对触发事件加条件判断
  //  事件名: (参数名) => {
  //    return true  //返回false时不触发事件
  //  }
  //},
  methods: {
    函数名() { //此函数仅仅用于调用,触发以下代码
      this.$emit(‘事件名’, 参数值);   //子组件触发上面父组件中的事件,传递数据
    }
  },
}
</script>

5.子组件与父组件数据双向绑定:
(1)父组件实现:
<template>
  <子组件名 v-model:子组件的组件属性名="父的属性名"></子组件> <!-- v-model固定,用于双向绑定,当子组件的组件属性名为modelValue时,简写为v-model=”父的属性名” -->
</template>
<script>
import 子组件名 from '@/components/子组件文件名.vue';
export default {
  data(){
    return {
      父的属性名: '值',
    }
  },
  components: {
    子组件名
  }
}
</script>

(2)子组件实现:
export default {
  props: {
'子组件的组件属性名': String,  //名称为modelValue时,上面可以简写为v-model
  //'modelModifiers': { //modelModifiers为固定名,用于接收父组件v-model的修饰符:this.modelModifiers.修饰符
  //  default: ()=> ({})  //v.model没有修饰符时返回{}
  //}
},
  methods: {
    函数名() { //此方法仅仅用于调用,触发以下代码
      this.$emit(‘update:子组件的组件属性名’, 参数值);   //update为固定名,用于双向绑定
    }
  },
}
</script>

6.插槽<slot>标签使用:
说明:父组件向子组件传递html标签、组件标签、字符串等布局内容,并在子组件中显示。
(1)方式1,父组件向子组件插入一种布局:
父组件实现:
<template>
   <子组件名> <!- 此方式用于不需要接收子组件数据时 -->
<!--<子组件名 v-slot="{子组件自定义名}"> --> <!-- 接收子组件数据,方式1 -->
<!--<子组件名 v-slot="父自定义名"> --> <!-- 接收子组件数据,方式2 -->
<div></div>  <!-- 将此内容插入到子组件中 -->
<!--   <div>{{ 子组件自定义名}}</div> --> <!-- 方式1,显示子组件的数据 -->
<!--   <div>{{ 父自定义名.子组件自定义名}}</div> --> <!-- 方式2,显示子组件的数据 -->
   </子组件名>
</template>
子组件实现:
<template>
  <slot></slot>   <!-- 使用slot标签显示父组件传入的布局 -->
<!-- <slot v-bind:子组件自定义名="属性名"></slot> --> <!-- 需给父组件传递数据时 -->
</template>
export default {
  data() { return {属性名: '值'}}
}
</script>

(2)方式2(具名插槽),父组件向子组件插入多种布局:
父组件实现:
<template>
  <子组件名>
<template v-slot:父布局名1>  <!-- 每种布局需要定义名称,格式 v-slot:名称 -->
<!--<template #父布局名1>-->  <!-- 简写方式,同上 -->
      <div>...</div>
    </template>
    <template v-slot:父布局名2>
      <div>...</div>
    </template>
  </子组件名>
</template>
子组件实现:
<template>
  <slot name="父布局名1"></slot>  <!-- 使用slot标签显示父组件传入的布局 -->
  <div>子组件内容</div>
  <slot name="父布局名2"></slot>
</template>

7.动态组件<component>使用:
说明:<component>根据传入的组件名动态显示组件
<template>
    <keep-alive> <!--缓存组件的状态数据,避免动态切换组件导致的数据丢失 -->
      <component v-bind:is="属性名1"/> <!-- component标签根据值控制显示哪个组件 -->
    </keep-alive>
</template>
<script>
export default {
  data(){return {
      属性名1: '组件名' //属性值必须为某个组件名,否则<component>不会显示组件内容
    } },}
</script>

8.异步加载组件:
说明:通过异步方式,需要显示页面时再加载组件
<script>
import { defineAsyncComponent } from 'vue'  //导入异步加载库
import加载中组件名 from '../components/加载中组件文件名.vue'
import 错误页组件名 from '../components/错误页组件文件名.vue'
export default {
  components: {
//    组件名: defineAsyncComponent( //方式1,无加载中、无错误页
//      () => import('../components/组件文件名.vue'),       //异步加载方式 显示此组件
//    ),
组件名: defineAsyncComponent({ //方式2,显示加载中、加载失败时显示错误页
      loader: () => import('../components/组件文件名.vue'),  //异步加载方式 显示此组件
      loadingComponent: 加载中组件名,  //加载中显示的组件
      delay: 200,                       //显示加载组件前的延迟时间,默认为 200ms
      errorComponent: 错误页组件名,  //加载失败显示的组件
      timeout: 3000                  //加载超时时间
    }),
  }
}
</script>

9.provide与inject(孙组件跨层级取爷组件属性值):
(1)爷组件:
方式一,选项式:
export default {
  provide: { //此处定义需要暴露给孙组件的属性名
    爷暴露名: '值'
  },
// provide() { //同上
//   return {爷暴露名: this.属性名}  //此种方式可以使用data中定义的属性
// },
}
</script>
方式二,组合式:
<script setup>
import { ref, provide } from 'vue'
const 属性名 = ref('值')
provide('爷暴露名', 属性名)   //暴露属性
provide('爷暴露函数名', () => { //暴露函数
  //...
})
</script>

(2)孙组件:
方式一,选项式:
<script>
export default {
  inject: ['爷暴露名'], //取爷属性
}
</script>                           
<template>
  <div>{{ 爷暴露名}}</div> <!-- 显示爷属性值 -->
</template>
方式二,组合式:
<script setup>
import { inject } from 'vue'
const 属性引用名 = inject('爷暴露名', '属性默认值')  //取爷组件属性
const 函数引用名 = inject('爷暴露函数名')            //取爷组件方法
</script>
<template>
  <div v-on:click="函数引用名">{{ 属性引用名 }}</h1>
</template>

10.混入对象(封装通用函数/属性):
(1)编写混入对象内容,在src/plugins/混入对象文件名.js中:
export default {
    created() {  //vue生命周期函数(实例生成后执行,优先于app的created)
    },
    data() {  //定义属性列表
        return {
            属性名: '值'  //使用:{{ 属性名 }}
        }
    },
    属性名1: '值1',    //定义不放入data的自定义属性  //使用:{{ this.$options.属性名1 }}
    methods: { //定义函数列表
        函数名() {
            //...
        }
    }
}

(2)main.js中注册混入:
...
import MyMixins from './plugins/MyMixins.js'  //导入混入对象文件
const app = createApp(App)
app.mixin(MyMixins) //注册混入对象
app.mount('#app')
app.config.optionMergeStrategies.属性名 = (mixinVal, appValue) => { //混入对象与组件中存在同名属性时,优先使用混入对象中的(未加此配置时默认组件同名属性优先)
    return mixinVal || appValue;
}

(3)在其他组件中使用混入对象定义的属性或方法:
<template>
    <h1 v-on:click="函数名">{{ 属性名 }}</h1>
</template>

11.插件(封装通用函数/属性):
(1)编写插件内容,在src/plugins/插件文件名.js中:
export default {
    install: (app, options) => { //定义插件
       app.provide('属性名', '属性值');  //定义属性
       app.provide('函数名', function(){  //定义函数
            //...
       });
       app.directive('自定义指令', {  //定义自定义指令
            钩子函数名(el) { //实现vue生命周期函数
                 //实现自定义指令具体逻辑
            }
       })
       app.mixin({ //定义混入对象
          //...
})
       app.config.globalProperties.$新字段名 = '新值'; //给vue底层增加新的属性并赋值,使用:this.$新字段名
       app.config.globalProperties.$新函数名 = function () { //给vue底层增加新的函数,调用:this.$新函数名()
         //...
      };
    },
}

(2)main.js中注册为插件:
...
import 插件名 from './plugins/插件文件名.js'  //导入上面定义的插件文件
const app = createApp(App)
app.use(插件名)  //注册为插件
app.mount('#app')

(3)在其他组件中使用插件定义的属性或方法:
<template>
    <h1 v-on:click="函数名">{{ 属性名 }}</h1>  <!-- 使用插件中定义的属性、函数 -->
</template>
<script>
export default {
    inject: ['属性名', '函数名'],  //注入插件中定义的属性、函数
}
</script>

12.render函数:
说明:能实现<template>的功能。
app.component('组件名', {
    render(){
        const { h } = Vue;  //引入h函数
        return h('html标签名', {}, this.$slots.default()) //利用h函数,调用此标签,第一个参数为标签名, 第2个参数为自定义组件标签传入的属性值参数,第3个参数为自定义组件包含的内容
    }
})


三、自定义指令:
钩子函数名:
created : 在绑定元素的属性或事件监听器被应用之前调用。
beforeMount : 指令第一次绑定到元素并且在挂载父组件之前调用。。
mounted : 在绑定元素的父组件被挂载后调用。。
beforeUpdate: 在更新包含组件的 VNode 之前调用。。
updated: 在包含组件的 VNode 及其子组件的 VNode 更新后调用。
beforeUnmount: 当指令与在绑定元素父组件卸载之前时,只调用一次。
unmounted: 当指令与元素解除绑定且父组件已卸载时,只调用一次。

钩子函数参数:
el: 使用此指令的html标签引用,可操作 DOM,例el.innerHTML = “值”
binding: 传给指令的对象,含以下属性:
- instance:使用指令的组件实例
- value:传递给自定义指令的值,取参数值:binding.value
- oldValue:旧值,仅在 beforeUpdate函数、 updated 函数中可用
- arg:传递给自定义指令的参数名。取参数名:binding.arg
- modifiers:包含修饰符的对象
- dir:指令对象本身,例:{钩子函数名(el){...}}
vnode:  el参数收到的真实DOM元素的节点
prevNode: 上一个虚拟节点,仅在 beforeUpdate函数、updated函数中可用

1.定义为全局指令:
说明:main.js中定义指令,在其他vue文件中使用
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.directive('自定义指令名', {  //全局自定义指令,使用:<div v-自定义指令名 />
钩子函数名(el, binding, vnode){ //钩子函数见上面,取参数名:binding.arg, 取参数值:binding.value
//function(){ //不用钩子函数时可以省略钩子函数名
       //执行指令具体逻辑
    }
})

2.定义为局部指令:
说明:在使用自定义指令的vue文件中定义+使用
<script>
export default {
   directives: {  // 局部自定义指令,使用:<div v-自定义指令名 />
     自定义指令名: {   
       钩子函数名(el) {
          //执行指令具体逻辑
       }
     }
   }
}
</script>

3.使用自定义指令:
<template>
  <html标签名 v-自定义指令名 />
<html标签名 v-自定义指令名:自定义参数名=”参数值” />  //给自定义指令传值
</template>

四、路由跳转:
1.定义路由:
(1)工程/src/router/index.js中配置路由:
import { createRouter, createWebHistory } from 'vue-router' //导入路由依赖库
const 路由列表名 = [                 // 1. 路由列表,映射路径到页面
{ path: '/路径名', component: () => import('../views/页面文件名.vue') },    //path配置路由路径,component配置页面vue文件路径,使用:<router-link to="/路径名”>
{ path: '/:pathMatch(.*)*', component: () => import('../views/错误页.vue') }, //捕获所有404 路由
]
const 路由实例名 = createRouter({    //2. 根据路由列表创建路由实例
history: createWebHistory(process.env.BASE_URL),,  //或createWebHashHistory
//routes: 路由列表名     //等同下面 
routes  //路由列表名为routes时,可以用此缩写方式
})
export default 路由实例名            //3.导出路由实例

(2)main.js中使用路由配置:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'  //导入路由目录(工程/src/router)
const app = createApp(App)
app .use(router).mount('#app')  //使用路由配置
 
3.使用路由:
<router-link>标签属性说明:
replace:导航后不会留下记录,例<router-link to="路径" replace />
append:从 /a1 导航到一个相对路径 a2,没有配append时路径为/a2,如果配了,则为/a1/a2,例<router-link to="路径" append />
tag:将<router-link>显示为其他标签(功能不变),例<router-link to="路径" tag="div" />,<router-link>显示为<div>...</div>
active-class:模糊匹配链接激活时显示的CSS样式,例<router-link to="路径" active-class="CSS样式名" />
exact-active-class:精准匹配链接激活时显示的CSS样式,例<router-link to="路径" exact-active-class="CSS样式名" />
event:触发导航的事件,例<router-link to="路径" event="字符串或字符串数组" />

使用路由(<router-link>和<router-view>):
<template>
  <router-link to="/路径名”>...</router-link>    //此路径与路由中配置的一致,点击时将路由组件显示在<router-view>中
  <router-link :to="'/路径名'">...</router-link> //用v-bind,效果同上
<router-link :to="{path: '/路径名'}">...</router-link>    //同上,显式写了path
  <router-link :to="{name: '/路径名', params: { 参数名: 值 }}">...</router-link> //命名的路由
  <router-link :to="{path: '/路径名' query: { 参数名: '值' }}">...</router-link>    //带参数的路径,/路径?参数名=值
  以下显示路由后的页面内容:
  <router-view/>                  //路由页面内容显示在<router-view>中
</template>

五、Composition API:
1.readonly使用:
作用:包装原对象为只读
<script setup>
import { reactive, readonly} from 'vue'  //导入ref
const 原对象名 = reactive({字段名: '值'})
const 包装对象名 = readonly(原对象名)  //包装原对象为只读, 使用:{{ 包装对象名.字段名 }}
</script>

2.toRefs使用:
作用:解构对象,取对象字段
<script setup>
import { reactive, toRefs} from 'vue'  //导入ref
const 对象名 = reactive({字段名: '值'})
const { 字段名 } = toRefs(对象名) //解构对象,取对象字段,改此值时对象字段的值也跟着变化,使用: {{ 字段名 }}
</script>
<template>
{{ 字段名 }}
</template>

3.toRef使用:
作用:取对象字段,改别名值时对象字段的值也跟着变化
<script setup>
import { reactive, toRef } from 'vue'  //导入ref
const 对象名 = reactive({字段名: '值'})
const 字段别名 = toRef(对象名, '字段名') //取对象字段,改别名值时对象字段的值也跟着变化,使用: {{ 字段别名 }}
</script>
<template>
{{ 字段别名 }}
</template>

4.context参数:
<script setup>
import { getCurrentInstance } from 'vue'  //导入ref
const context = getCurrentInstance().ctx; //获取context参数
context.props  // 访问props, 用于组件标签属性传值
context.attrs   // 访问attrs
context.slots   // 访问slots,等同插槽<slot>标签
context.emit('事件名')  // 访问emit, <子组件名 @事件名="父函数名" />
</script>

六、vuex全局数据管理:
说明:vuex可定义全局属性,供所有组件读/写
1.定义全局属性,在src/store/index.js中:
import { createStore } from 'vuex'
export default createStore({ //全局数据管理
  state: {    //1.定义属性列表
    属性名: '值'
  },
  getters: {},
  mutations: { //4.修改属性值
    mutation名1(state, newValue){ //参数由commit传入
      state.属性名 = newValue  //将外部传入的新值赋给属性
    }
  },
  actions: {  //3.接收外部事件,提交到mutations
    事件名1(store, newValue){ //参数由外部传入
      store.commit('mutation名1', newValue)  //提交到mutations
    }
  },
  modules: {}
})

2.读/写全局属性:
方式1,选项式:
<script>
export default {
  methods: {
    函数名(){
      this.$store.dispatch('事件名1', '新值') //触发createStore.actions定义的事件名1
    }
  }
}
</script>
<template>
  <div v-on:click="函数名">点击修改全局属性</div>
  {{ this.$store.state.name }}    <!-- 读全局属性 -->
</template>
方式2,组合式:
<script setup>
import { useStore } from "vuex"
const store = useStore()  //获取store引用
function 函数名(){
  store.dispatch('事件名1', '新值') //触发createStore.actions定义的事件名1
}
</script>
<template>
  <div v-on:click="函数名">点击修改全局属性</div>
  {{ this.$store.state.name }}   <!-- 读全局属性 -->
</template>


七、动画:
1.定义过渡动画Class:
过渡名(固定名称):
enter-from:进入过渡动画的开始状态
enter-active:进入过渡动画的持续状态(在此定义持续时间、延迟、速度、曲线类型)
enter-to:进入过渡动画的结束状态
leave-from:离开过渡动画的开始状态
leave-active:离开过渡动画的持续状态(在此定义持续时间、延迟、速度、曲线类型)
leave-to:离开过渡动画的结束状态
Move:移动时的动画效果

(1) .v-过渡名 方式定义Class名:
格式:.v-过渡名
例:
.v-enter-active{ //格式:.v-过渡名
    //编写CSS动画
}

(2).动画名-过渡名 方式定义Class名:
动画名(固定名称):
fade:渐隐动画
slide-fade:滑动+渐隐动画
bounce:弹动动画

格式:.动画名-过渡名
例:
.fade-enter-active{ //格式:.动画名-过渡名
    //编写CSS动画
}

2.使用<Transition>标签展示动画:
说明:v-show或v-if的值改变时触发动画
(1)name属性+动画名方式:
<template>
   <Transition name = "fade"> //fade为动画名(名称固定,不可自定义),与 .动画名-过渡名中的动画名保持一致
      <div v-show="true或false">...</div>  //要动画的布局,通过改变v-show或v-if的值触发动画
   </Transition>
</template>

(2)过渡名-class 作为<Transition>属性方式:
属性名(属性名固定):
enter-from-class
enter-active-class
enter-to-class
leave-from-class
leave-active-class
leave-to-class
例:
<template>
   <Transition 
      enter-active-class="自定义class名1"  
      leave-active-class="自定义class名2">  //class可自定义或使用三方动画库
      <div v-show="true或false">...</div>
   </Transition>
 </template>

(3)其他<Transition>特性:
<1>过渡动画持续时间:
<Transition :duration="毫秒数">
//<Transition :duration="{ enter: 进场毫秒数, leave: 离场毫秒数 }">
   ...
</Transition>

<2>给动画过程添加监听函数(在函数中实现动画):
<Transition 
:css="false"                   <!-- 取消CSS动画使用函数中的JS实现动画 -->
@before-enter="自定义函数名"  <!-- 在元素被插入到 DOM 之前被调用 -->
@enter="自定义函数名"   <!-- 在元素被插入到 DOM 之后的下一帧被调用 -->
@after-enter="自定义函数名"   <!-- 当进入过渡完成时调用 -->
@enter-cancelled="自定义函数名"   <!-- 当进入过渡在完成之前被取消时调用 -->
@before-leave="自定义函数名"   <!-- leave之前调用 -->
@leave="自定义函数名"   <!-- 离开过渡开始时调用 -->
@after-leave="自定义函数名"   <!-- 离开过渡完成时调用 -->
@leave-cancelled="自定义函数名" >  <!-- 仅 v-show 过渡中可用 -->
   ...
</Transition>

<3>mode属性可实现单个元素切换效果(不加mode默认同步执行动画):
<Transition mode="out-in | in-out" appear> ... </Transition>  //appear表示初始化显示时有也动画效果

3.使用<TransitionGroup>标签展示动画:
说明:v-for 列表中的元素插入、移除和顺序改变时触发动画
<template>
  <TransitionGroup>
    <div v-for="(item, index) in list" v-bind:key="item">{{ item }}</div> <!--列表变化时触发动画-->
  </TransitionGroup>
</template>


八、Ajax网络请求(axios框架):
cd到工程目录输入命令安装axios:
C:\Users\Administrator\Desktop\demo2> npm install axios

response响应数据结构说明:
{
  data: {},          //response.data,数据
  status: 200,       //response.status,HTTP 状态码
  statusText: "OK",  //response.statusText,HTTP 状态信息
  headers: {},       //response.headers,响应头
  config: {}         //response.config,请求提供的配置信息
}

1.GET方式请求:
方式1:
<script>
import axios from 'axios'  //导入axios
export default {
  methods: {
    doGet() { //自定义函数名
      // var cancelTask = axios.CancelToken.source(); //用于取消请求
      axios.get('url?参数=xxx')  //方式1,参数跟在url后面
      /*axios.get('url', {        //方式2,参数通过第2个参数传入,与上面等同
            params: { //参数列表
              参数: 值
            },
            headers: { //头字段列表
      ‘头字段名’: ‘值’
            },
            timeout: 300000,  //请求超时时长
          })*/
         .then(function (response) { //处理成功的数据,如json
          alert(response)
        })
        .catch(function (error) {  //处理失败的情况
          alert(error)
        });
        //取消请求
        //cancelTask.cancel('');
      }
    }
}
</script>

方式2:
<script>
import axios from 'axios'  //导入axios
export default {
  methods: {
  doPost() {
axios({ 
method: ‘get’, 
url: ‘url?参数=值’,
headers: {'头字段': '值'}
})
    .then(function (response) { //处理成功的数据,如json
    })
    .catch(function (error) {  //处理失败的情况
    });
   }
   }
}
</script>


2.POST方式请求:
方式1:
<script>
import axios from 'axios'  //导入axios
export default {
  methods: {
  doPost() { //自定义函数名
axios.post('url', 
{ //参数列表
        参数1: '值',
        参数2: '值'
},
{
headers: {'头字段': '值'} //头字段列表
}
)
    .then(function (response) { //处理成功的数据,如json
    })
    .catch(function (error) {  //处理失败的情况
    });
   }
   }
}
</script>

方式2:
<script>
import axios from 'axios'  //导入axios
export default {
  methods: {
  doPost() {
axios({ 
method: 'post', 
url: 'url', 
headers: {'头字段': '值'},
data: { 参数1: ‘值' }
})
    .then(function (response) { //处理成功的数据,如json
    })
    .catch(function (error) {  //处理失败的情况
    });
   }
   }
}
</script>

3.并发执行多个请求:
axios.all([doGet(), doPost()])   //并发执行上面的get与post请求,或者axios.spread
  .then(axios.spread(function (acct, perms) {
    // 两个请求执行完毕后回调
}));

4.修改默认值:
axios.defaults.headers.common['Authorization'] = “token值”;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

5.拦截器:
(1)请求拦截器:
axios.interceptors.request.use(function (config) {
    //发送请求之前时触发
    return config;
  }, function (error) {
    //请求错误时触发
    return Promise.reject(error);
  });

(2)响应拦截器:
axios.interceptors.response.use(function (response) {
    // 响应数据时触发
    return response;
}, function (error) {
    // 响应错误时触发
    return Promise.reject(error);
});

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值