Vue3 详细教程

2023-11-12

文章目录


提示:以下是本篇文章正文内容,前端系列学习将会持续更新

在这里插入图片描述
官网https://cn.vuejs.org

一、API 风格

1.1 选项式 API

使用选项式 API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 data、methods 和 mounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

<script>
  export default {
    data() {
      return {
        count: 0
      }
  	},
    methods: {
      increment() {
        this.count++
      }
    },
    mounted() {
      // 该函数就会在组件挂载完成后被调用
      // 一般进行网络请求,重新渲染数据
    }
  }
</script>

1.2 组合式 API

通过组合式 API,我们可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与 <script setup> 搭配使用。这个 setup attribute 是一个标识,告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。比如,<script setup> 中的导入和顶层变量/函数都能够在模板中直接使用。

下面是使用了组合式 API 与 <script setup> 改造后和上面的模板完全一样的组件:

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

<script setup>
  import { ref, onMounted } from 'vue'

  // 响应式状态
  const count = ref(0)

  // 用来修改状态、触发更新的函数
  function increment() {
    count.value++
  }

  // 生命周期钩子
  onMounted(() => {
    console.log(`The initial count is ${count.value}.`)
  })
</script>

回到目录…

二、Vue 指令

在这里插入图片描述

2.1 {{}} 文本插值

  • {{}} 的作用是:文本替换,内部可以计算数值
<template>
  <h2>{{ message }}世界</h2>      <!-- 你好!世界 -->
  <h2>{{ age + 1 }}</h2>    <!-- 13 -->
</template>
<script>
  export default {
    data() {
      return {
        message: "你好!",
        age: 12
      }
    }
  }
</script>

2.2 v-html 标签元素

  • v-html 指令的作用是:设置元素的 innerHTML
  • 内容中有 html 结构会被解析为标签。
  • 解析文本使用 {{}},需要解析 html 结构使用 v-html。
<template>
  <p v-html="message"></p>  <!-- <p><a href='https://www.baidu.com'>百度百科</a></p> -->
</template>
<script>
  export default {
    data() {
      return {
        message: "<a href='https://www.baidu.com'>百度百科</a>"
      }
    }
  }
</script>

2.3 v-on 绑定事件

  • v-on 指令的作用是:为元素绑定事件,包括:blur, focus, focusin, focusout, load, resize, scroll, unload, click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave,change, select, submit, keydown, keypress, keyup, error。
  • v-on 指令可以简写为 @,如 v-on:click="func()" 等同于 @click="func()"
  • 绑定的方法定义在 methods 属性中,方法内部通过 this 关键字可以访问定义在 data 中的数据。
<template>
  <p>{{message}}</p>
  <input type="button" value="触发事件1" v-on:click="func">
  <input type="button" value="触发事件2" @click="func2('张三')">
</template>
<script>
  export default {
    data() {
      return {
        message: "Hello,World!"
      }
    },
    methods: {
      func() {
        alert(this.message);
      },
      func2(name) {
        alert("你好," + name);
      }
    }
  }
</script>

2.4 v-show 隐藏元素

  • v-show 指令的作用是:根据真假切换元素的显示状态
  • v-show 原理是修改元素的 display 值,实现显示和隐藏。其值最终会解析为布尔值 (true元素显示,false元素隐藏)。
  • 数据改变之后,对应元素的显示状态会同步更新。
<template>
  <div v-show="isShow">模块一</div>
  <div v-show="num > 10">模块二</div>
</template>
<script>
  export default {
    data() {
      return {
        isShow: false,
        num: 18
      }
    }
  }
</script>

2.5 v-if 消除元素

  • v-if 指令的作用是:根据表达式的真假切换元素的显示状态
  • 本质是通过操纵 dom 元素来切换显示状态。表达式值为true时,元素存在于dom树中;值为false时,从dom树中移除。
  • 频繁的切换使用 v-show,反之使用 v-if,前者的切换消耗小。
<template>
  <div v-if="isShow">模块一</div>
  <div v-if="num > 10">模块二</div>
</template>
<script>
  export default {
    data() {
      return {
        isShow: false,
        num: 18
      }
    }
  }
</script>

2.6 v-bind 属性渲染

  • v-bind 指令的作用是:为元素绑定属性
  • v-bind 指令可简写为 : ,如 v-bind:src="imgSrc" 等同于 :src="imgSrc"
  • 需要动态的增删 class 时,建议使用对象的方式。
<template>
  <a v-bind:href="myHref">百度百科</a>
  <input type="button" :value="myVal">
</template>
<script>
  export default {
    data() {
      return {
        myHref: "https://www.baidu.com",
        myVal: "我的按钮"
      }
    }
  }
</script>

2.7 v-for 列表渲染

  • v-for 指令的作用是:根据数据生成列表结构。经常和数组结合使用。
  • v-for 语法是 item in arr(item,index) in arr,item 和 index 可以结合其他指令一起使用。
  • 当数组长度发生改变时,更新会同步到页面上,是响应式的。但它默认使用 “就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序。为了让 Vue 能跟踪每个节点的身份,从而重新排序现有元素,我们需要为 v-for 渲染的元素添加一个唯一的 key(可以使用index,但建议使用动态数据的唯一ID)
<template>
  <ul>
    <li v-for="item in vegetables">菜品:{{ item.name }}, 价格:{{ item.price }}</li>
  </ul>
  <p v-for="(it,index) in arr" :key="it.id|index">{{ index+1 }}.{{ it }}</p>
</template>
<script>
  export default {
    data() {
      return {
        arr:["北京","上海","广州","深圳"],
        vegetables:[
          {name:"西兰花炒蛋", price:20},
          {name:"蛋炒西蓝花", price:30}
        ]
      }
    }
  }
</script>

2.8 v-model 数据双向绑定

  • v-model 指令的作用是便捷的设置和获取表单元素的值
  • 绑定的数据会和表单元素值相关联,绑定的数据 <=> 表单元素的值。
<template>
  <input type="text" v-model="message">
  <p>动态修改massage值: {{ message }}</p>
</template>
<script>
  export default {
    data() {
      return {
        message:"沙丁鱼"
      }
    }
  }
</script>

回到目录…

三、组件

在这里插入图片描述

3.1 组件组合

①单文件组件(又名 *.vue 文件,缩写为 SFC) 是一种特殊的文件格式,它允许将 Vue 组件的模板逻辑样式封装在单个文件中。

<template>
  <h2>我的单文件组件</h2>
</template>

<script>
  export default {
    name: "MyComponent"
  }
</script>

<style scoped>  <!-- scoped表示只改变该文件的模板样式 -->
  h2 {
    color: red;
  }
</style>

②加载组件
第一步:引入组件 import MyComponent from './components/MyComponent.vue'
第二步:挂载组件 components: { MyComponent }
第三步:显示组件 <MyComponent/>

<template>
  <h2>APP.vue的二级标题</h2>
  <MyComponent/>
</template>

<script>
  import MyComponent from './components/MyComponent.vue';
  export default {
    name: "APP",
    components: {
      MyComponent
    }
  }
</script>

查看效果
在这里插入图片描述

③组件的组织:通常一个应用会以一棵嵌套的组件树的形式来组织。
在这里插入图片描述

回到目录…

3.2 Props 组件交互

  • 父组件向子组件传递数据,Props 可以在组件上注册的一些自定义属性将数据传给子组件。

①传递属性:父组件向子组件传递属性值。

父组件:App.vue

<template>
  <h2>APP.vue的二级标题</h2>
  <MyComponent :title="title" :arr="arr"/>
</template>

<script>
  import MyComponent from './components/MyComponent.vue';
  export default {
    name: "APP",
    data() {
      return {
        title: "传递字符串",
        arr: ["zhangsan","lisi","wangwu"]
      }
    },
    components: {
      MyComponent
    }
  }
</script>

子组件:MyComponent.vue

<template>
  <h2>Props 组件交互</h2>
  <p>{{ title }}</p>
  <p v-for="(item,index) in arr" :key="index">{{ item }}</p>
</template>

<script>
  export default {
    name: "MyComponent",
    props: {
      title: {
        type: String, //数据类型
        default: ""   //默认值
      },
      arr: {
        type: Array,
        default: function() {
          return [];
        }
      }
    }
  }
</script>

②Prop 类型:Prop传递参数其实是没有类型限制的。

注意:数据类型为数组或者对象的时候,默认值是需要返回工厂模式 (使用函数返回)。

props: {
  title: String, // 字符串类型
  likes: Number, // 数字类型
  isPublished: Boolean, // 布尔类型
  commentIds: Array, // 数组类型
  author: Object, // 对象类型
  callback: Function // 函数类型
}

回到目录…

3.3 自定义事件组件交互

  • 子组件向父组件传递数据,自定义事件可以在组件中反向传递数据。

子组件:MyComponent.vue

<template>
  <h2>自定义事件组件交互</h2>
  <input type="button" value="发送数据" @click="sendData">
</template>

<script>
  export default {
    name: "MyComponent",
    methods: {
      sendData() {
        // 参数一: 接收数据的事件名称,参数二: 发送的数据
        this.$emit("onEvent", {name:"zhangsan",age:18});
      }
    }
  }
</script>

父组件:App.vue

<template>
  <h2>APP.vue的二级标题</h2>
  <MyComponent @onEvent="getData"/>
</template>

<script>
  import MyComponent from './components/MyComponent.vue';
  export default {
    name: "APP",
    components: {
      MyComponent
    },
    methods: {
      getData(student) {
        alert("姓名:" + student.name + ",年龄:" + student.age);
      }
    }
  }
</script>

回到目录…

3.4 组件生命周期

每个组件在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

在这里插入图片描述

为了方便记忆,我们可以将他们分类:

  • 创建时: beforeCreatecreated
  • 渲染时: beforeMountmounted
  • 更新时: beforeUpdateupdated
  • 卸载时: beforeUnmountunmounted

回到目录…

四、Vue 引入第三方 Swiper

在这里插入图片描述

  • 官方文档https://swiperjs.com/vue
  • Swiper 开源、免费、强大的触摸滑动插件。
  • Swiper 是纯 JavaScript 打造的滑动特效插件,面向手机、平板电脑等移动终端。
  • Swiper 能实现触屏焦点图、触屏 Tab 切换、触屏轮播图切换等常用效果。

①安装指定版本: npm install --save swiper@8.1.6

②基础实现

<template>
    <div class="hello">
        <swiper class="mySwiper" :modules="modules" :pagination="{ clickable:true }">
            <swiper-slide><img src="../assets/1.png"></swiper-slide>
            <swiper-slide><img src="../assets/2.png"></swiper-slide>
            <swiper-slide><img src="../assets/3.png"></swiper-slide>
        </swiper>
    </div>
</template>

<script>
import { Swiper, SwiperSlide } from 'swiper/vue'; //核心组件
import { Pagination } from 'swiper'; //指示器组件
import 'swiper/css';
import 'swiper/css/pagination';

export default {
    name: "HelloWorld",
    data() {
        return {
            modules: [Pagination]
        }
    },
    components: {
        Swiper,
        SwiperSlide
    }
}
</script>

<style scoped>
    img {
        width: 100%;
    }
</style>

效果展示
在这里插入图片描述

回到目录…

五、Axios 网络请求库

官网https://github.com/axios/axios

在这里插入图片描述

5.1 基本使用

①安装依赖

# Axios 需要单独安装 
npm install --save axios
# post 请求参数是需要额外处理,安装依赖; 参数转换格式: qs.stringify({})
npm install --save querystring

②组件中引入import axios from "axios"

③GET请求

axios({
    method: "get",
    url: "http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php"
}).then(res => {
    console.log(res.data);
})
axios.get("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php")
.then(res => {
	console.log(res.data);
})

④POST请求

axios({
    method: "post",
	url: "http://iwenwiki.com/api/blueberrypai/login.php",
    data: qs.stringify({
        user_id: "iwen@qq.com",
        password: "iwen123",
        verification_code: "crfvw"
    })
}).then(res =>{
    console.log(res.data);
})
axios.post("http://iwenwiki.com/api/blueberrypai/login.php", qs.stringify({
	user_id: "iwen@qq.com",
	password: "iwen123",
    verification_code: "crfvw"
})).then(res => {
	console.log(res.data);
})

回到目录…

5.2 Axios 网络请求封装

在实际应用过程中,一个项目中的网络请求会很多,此时一般采取的方案是将网络请求封装起来。

①我们先创建 src/utils/request.js 文件,用来存储网络请求对象 axios。
参考文档Axios 看云

import axios from "axios"
import qs from "querystring"

const errorHandle = (status,info) => {
    switch(status) {
        case 400: console.log("语义有误"); break;
        case 401: console.log("服务器认证失败"); break;
        case 403: console.log("服务器拒绝访问"); break;
        case 404: console.log("地址错误"); break;
        case 500: console.log("服务器遇到意外"); break;
        case 502: console.log("服务器无响应"); break;
        default: console.log(info); break;
    }
}

const instance = axios.create({
    timeout:5000 // 网络请求的公共配置: 请求超时时间
})

// 发送数据前的拦截器
instance.interceptors.request.use(
    config => {
        if(config.method === "post") {
            config.data = qs.stringify(config.data);
        }
        return config; // 包括网络请求的所有信息
    },
    error => Promise.reject(error)
)
// 获取数据前的拦截器
instance.interceptors.response.use(
    response => response.status === 200 ? Promise.resolve(response) : Promise.reject(response),
    error => {
        const { response } = error;
        errorHandle(response.status, response.info);
    }
)

export default instance;

②创建 src/api/path.js 用来存放网络请求路径;创建 src/api/index.js 用来存放网络请求路径

// path.js
const base = {
    baseUrl:"http://iwenwiki.com",
    chengpin:"/api/blueberrypai/getChengpinDetails.php"
}
export default base
// index.js
import path from "./path"
import axios from "../utils/request"

export default {
    getChengpin() {
        return axios.get(path.baseUrl + path.chengpin);
    }
}

③在组件中直接调用网络请求

<script>
import api from './api/index';
export default {
    name: "APP",
    mounted() {
        api.getChengpin().then(res => {
            console.log(res.data);
        })
    }
}
</script>

回到目录…

5.3 网络请求跨域解决方案

JS 采取的是同源策略。同源策略是浏览器的一项安全策略,浏览器只允许 js 代码请求当前所在服务器的域名、端口、协议相同的数据接口上的数据,这就是同源策略
也就是说,当协议、域名、端口任意一个不相同时,都会产生跨域问题,所以又应该如何解决跨域问题呢?

跨域错误提示信息http://iwenwiki.com/api/FingerUnion/list.php
在这里插入图片描述
目前主流的跨域解决方案有两种:后台解决:cors;前台解决:proxy

①我们找到父工程下的 vue.config.js 或 vite.config.js 文件,向它的 defineConfig 项中添加以下配置:

// vue.config.js配置
devServer: {
  proxy: {
  '/api': {
    target: 'http://xxxxxxxxxxx.xxx/api',
    changOrigin: true,
    pathRewrite: {
      '^/api': ''
    }
  }
}
// vite.config.js配置
server: {
  proxy: {
    '/api': {
      target: 'http://iwenwiki.com/api', // 凡是遇到 /api 路径的请求,都映射到 target 属性
      changeOrigin: true,
      rewrite: path => path.replace(/^\/api/, '') // 重写 /api 为 空,就是去掉它
    }
  }
}

②如何访问跨域的地址?

mounted() {
  // 使用'/url'代替域名部分即可
  axios.get("/api/FingerUnion/list.php")
  .then(res => {
    console.log(res.data);
   })
}

注意:解决完跨域配置之后,要记得重启服务器才行哦!

回到目录…

六、Vue Router 路由

官方文档https://router.vuejs.org/zh

在这里插入图片描述

在 Vue 中,我们可以通过 vue-router 路由管理页面之间的关系,Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让 Vue.js 构建单页应用变得轻而易举。

6.1 引入路由

第一步:安装路由 npm install --save vue-router

第二步:配置独立的路由文件 src/router/index.js

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
    {
        path: '/',
        name: 'home',
        component: Home
    },
    {
        path: '/about',
        name: 'about',
        component: () => import('../views/About.vue') //异步加载方式
    }
]

const router = createRouter({
    /**
     * createWebHashHistory
     *      home: http://localhost:5176/#/
     *      about: http://localhost:5176/#/about
     * 原理: a标签锚点链接
     * 
     * createWebHistory, 此种方式需要后台配合做重定向,否则会出现404问题
     *      home: http://localhost:5176/
     *      about: http://localhost:5176/about
     * 原理: HTML5的pushState()
     */
    history: createWebHashHistory(),
    routes
})

export default router

第三步:引入路由到项目,在 src/main.js 中添加 use(router)

import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')

第四步:指定路由显示入口、路由跳转

<template>
  <nav>
    <RouterLink to="/">主页</RouterLink> | 
    <router-link to="/about">关于</router-link>
  </nav>
  <RouterView></RouterView> <!-- 路由跳转入口 -->
</template>

在这里插入图片描述

回到目录…

6.2 根据URL参数路由

页面跳转过程中,是可以携带参数的,这也是很常见的业务,比如我们的分页功能、商品项详情。

第一步:在路由配置中指定参数的 key

{
    path: '/news/details/:name',
    name: 'newsdetails',
    component: () => import('../views/NewsDetails.vue') //对应新闻详情页
}

第二步:在跳转过程中携带参数

<template>
    <h1>News页面</h1>
    <ul>
        <li><RouterLink to="/news/details/百度">百度新闻</RouterLink></li>
        <li><RouterLink to="/news/details/新浪">新浪新闻</RouterLink></li>
        <li><RouterLink to="/news/details/网易">网易新闻</RouterLink></li>
    </ul>
</template>

第三步:在详情页面读取路由携带的参数

<template>
    <h1>新闻详情</h1>
    <p>{{ $route.params.name }}</p>
</template>

在这里插入图片描述

回到目录…

6.3 多级路由嵌套

路由嵌套是十分常见的需求,比如二级导航。
在这里插入图片描述

第一步:创建子路由要加载显示的页面
关于我们的页面:src/views/aboutsub/AboutUS.vue
更多信息的页面:src/views/aboutsub/AboutInfo.vue

第二步:在路由配置文件中添加子路由配置

{
	path: '/about',
    name: 'about',
    redirect: '/about/us', //重定向到指定的子路由
    component: () => import('../views/About.vue'),
    children: [
        {
            path: 'us', //子路由不加'/'
            component: () => import('../views/aboutsub/AboutUS.vue')
        },
        {
            path: 'info',
            component: () => import('../views/aboutsub/AboutInfo.vue')
        }
    ]
}

第三步:指定子路由显示位置、跳转链接

<template>
    <h1>About页面</h1>
    <RouterLink to="/about/us">关于我们</RouterLink> | 
    <RouterLink to="/about/info">更多信息</RouterLink>
    <RouterView></RouterView>
</template>

在这里插入图片描述

回到目录…

七、Vuex 状态管理

官方文档https://vuex.vuejs.org/zh/index.html
在这里插入图片描述
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

简单来说,状态管理可以理解成为了更方便的管理组件之间的数据交互,提供了一个集中式的管理方案,任何组件都可以按照指定的方式进行读取和改变数据。

如何引入Vuex?

第一步:安装Vuex npm install --save vuex

第二步:配置Vuex文件,创建 src/store/index.js

import { createStore } from 'vuex'
// Vuex的作用就是帮助我们管理组件之间的状态的
export default createStore({
    state: {
        // 所有状态(数据)都存储在这里
    },
    getters: {
        // 可以通过这里的方法进行数据过滤
    },
    mutations: {
        // 数据更改
    },
    actions: {
        // 数据异步更改
    }
})

第三步:在 main.js 主文件中引入Vuex

import store from './store'
createApp(App).use(store).mount('#app')

回到目录…

7.1 State 数据存储

①所有数据存储在 state 中:

state: {
	num: 13
}

②在组件中读取数据:

<p>{{ $store.state.num }}</p>

或者

<template>
  <p>{{ num }}</p>
</template>

<script>
  import { mapState } from 'vuex';
  export default {
    name: "APP",
    computed: {
      ...mapState(['num'])
    }
  }
</script>

回到目录…

7.2 Getter 数据过滤

①对 Vuex 中的数据进行过滤:

getters: {
	getNum(state) {
		return state.num>18 ? state.num : '未成年'
    }
}

②在组件中获取过滤后的数据:

<p>{{ $store.getters.getNum }}</p>

或者

<template>
  <p>{{ num }}</p>
  <p>{{ getNum }}</p>
</template>

<script>
  import { mapState, mapGetters } from 'vuex';
  export default {
    name: "APP",
    computed: {
      ...mapState(['num']),     // 直接获取数据
      ...mapGetters(['getNum']) // 获取过滤数据
    }
  }
</script>

回到目录…

7.3 Mutation 数据更改

Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type) 和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。

①更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

mutations: {
	incrNum(state) {
		state.num++
	},
    addNum(state,n) {
        state.num += n
    }
}

②在组件中通过触发事件来修改数据:

<template>
  <button @click="onEvent">修改数据</button>
  <button @click="onEvent2">修改数据2</button>
</template>

<script>
  export default {
    name: "APP",
    methods: {
      onEvent() {
        this.$store.commit('incrNum')
      },
      onEvent2() {
        this.$store.commit('incrNum', 10)
      }
    }
  }
</script>

或者

<template>
  <button @click="onEvent3">修改数据3</button>
</template>

<script>
  import { mapState, mapGetters, mapMutations } from 'vuex';
  export default {
    name: "APP",
    methods: {
      ...mapMutations(['addNum']),
      onEvent3() {
        this.addNum(20)
      }
    }
  }
</script>

回到目录…

7.4 Action 异步更改

Action 类似于 mutation,实际上 Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。

①对 Vuex 中的数据进行异步更改

mutations: {
    addNum(state,n) {
        state.num += n
    }
},
actions: {
	asyncAddNum({ commit }) {
        axios.get('http://iwenwiki.com/api/generator/list.php')
        .then(res => {
            commit('addNum', res.data[0]) // 调用mutations中的方法
        })
    }
}

②在组件中通过触发事件来进行异步修改:

<template>
  <button @click="asyncEvent">异步修改</button>
</template>

<script>
  export default {
    name: "APP",
    methods: {
      asyncEvent() {
        this.$store.dispatch('asyncAddNum')
      }
    }
  }
</script>

或者

<template>
  <button @click="asyncEvent2">异步修改2</button>
</template>

<script>
  import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
  export default {
    name: "APP",
    methods: {
      ...mapActions(['asyncAddNum']),
      asyncEvent2() {
        this.asyncAddNum()
      }
    }
  }
</script>

回到目录…

八、Vue3 组合式 API

  • Vue3 是目前 Vue 的最新版本,自然也是新增了很多新特性。
  • Performance:性能更比 Vue 2.0 强。
  • Tree shaking support:可以将无用模块“剪辑”,仅打包需要的。
  • Composition API:组合 API。
  • Fragment, Teleport, Suspense:“碎片”,Teleport 即 Protal 传送门,“悬念”。
  • Better TypeScript support:更优秀的Ts支持。
  • Custom Renderer API:暴露了自定义渲染 API。

8.1 ref 和 reactive

  • ref 通常用来定义基本类型数据;reactive 通常用来定义对象或数组类型数据。
  • ref 也可以用来定义对象或者数组类型的数据,内部会通过 reactive 转为代理对象。
<template>
  <div id="app">
    <p>{{ message }}</p>
    <p v-for="(item,index) in citys.arr" :key="index">{{ item }}</p>
    <p v-for="(item,index) in list" :key="index">{{ item }}</p>
    <p>{{ citys.age }}</p>
  </div>
</template>

<script>
import {ref, reactive} from 'vue'
export default {
  setup() {
    const message = ref('张三')
    const list = ref(['a','b','c'])
    const citys = reactive({
      arr: ['北京','上海','广州','深圳'],
      age: 18
    })
    return {
      message,
      citys,
      list
    }
  }
}
</script>

回到目录…

8.2 setup() 定义方法

  • 在 setup() 中不仅可以定义数据,还可以定义方法 (以lamada表达式的方式)。
  • 在 setup() 中定义的数据和方法,都需要使用 return 返回才能被调用。
<template>
  <div id="app">
    <button @click="onEvent">不带参数</button>
    <button @click="onEvent2('张三')">携带参数</button>
    <button @click="changeData">修改数据</button>
  </div>
</template>

<script>
import {ref, reactive} from 'vue'
export default {
  setup() {
    const onEvent = () => {
      alert('触发事件');
    }
    const onEvent2 = (arg) => {
      alert(arg);
    }
    const changeData = () => {
      message.value = '李四'
    }
    return {
      onEvent,
      onEvent2,
      changeData
    }
  }
}
</script>

回到目录…

8.3 props 和 context

在2.x中,组件的方法中可以通过this获取到当前组件的实例,并执行 data 变量的修改,方法的调用,组件的通信等等,但是在3.x中,setup() 在 beforeCreate 和 created 时机就已调用,无法使用和2.x一样的 this,但是可以通过接收 setup(props,ctx) 的方法,获取到当前组件的实例和 props。

父组件发送数据

<template>
  <div id="app">
    <Home title="哈哈"/>
  </div>
</template>

<script>
import Home from './views/Home.vue'
export default {
    components: { Home }
}
</script>

子组件接收数据:props 的新用法。

<template>
    <h1>Home页面</h1>
    <p>{{ title }}</p>
</template>

<script>
export default {
    name: 'home',
    props: {
        title: String
    },
    setup(props) {
        const title = props.title
        return {
            title
        }
    }
}
</script>

子组件发送数据:setup() 中取消了 this 关键字,而是用 context 代替。

<template>
    <h1>Home页面</h1>
    <input type="button" value="发送数据" @click="sendData">
</template>

<script>
export default {
    name: 'home',
    setup(props,ctx) {
        const sendData = () => {
            ctx.emit("onEvent", {name:"zhangsan",age:18});
        }
        return {
            sendData
        }
    }
}
</script>

父组件接收数据

<template>
  <div id="app">
    <Home @onEvent="getData"/>
  </div>
</template>

<script>
import Home from './views/Home.vue'
export default {
	components: { Home },
    setup() {
        const getData = (student) => {
          alert("姓名:" + student.name + ",年龄:" + student.age);
        }
        return {
            getData
        };
    }
}
</script>

回到目录…

8.4 Provide 和 Inject

  • provide() 和 inject() 可以实现嵌套组件之间的数据传递,这两个函数只能在 setup() 函数中使用。
  • 父级组件中使用 provide() 函数向下传递数据;子级组件中使用 inject() 获取上层传递过来的数据。
  • 不限层级。
// 父组件
import {provide} from 'vue'
import Home from './views/Home.vue'
export default {
    components: { Home },
    setup() {
        provide('num', 18);
    }
}
// 子组件
import { inject } from 'vue';
export default {
    setup() {
        const num = inject('num')
        return {
            num
        }
    }
}

回到目录…

8.5 setup中生命周期钩子

Options API Hook inside setup
beforeCreate Not needed*
created Not needed*
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted

在 setup() 中可以定义多个相同的生命周期函数,并且在周期内都会执行。

export default {
  setup() {
    onMounted(() => {
      console.log('业务一')
    })
    onMounted(() => {
      console.log('业务二')
    })
  }
}

回到目录…

九、Element-plus

官网Element Plus, 面向设计师和开发者的组件库
在这里插入图片描述

安装 Element-Plusnpm install element-plus --save

9.1 加载组件

方式一:完整引用,如果你对打包后的文件大小不是很在乎,那么使用完整导入会更方便。

// main.js
import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

createApp(App).use(ElementPlus).mount('#app')

方式二:按需导入才是我们的最爱,毕竟在真实的应用场景中并不是每个组件都会用到,这会造成不小的浪费。

①首先你需要安装 unplugin-vue-componentsunplugin-auto-import 这两款插件。

npm install -D unplugin-vue-components unplugin-auto-import

②然后修改 vue.config.js 或 vite.config.js 配置文件

// vue.config.js
const { defineConfig } = require('@vue/cli-service')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: {
    plugins: [
      AutoImport({
        resolvers: [ElementPlusResolver()]
      }),
      Components({
        resolvers: [ElementPlusResolver()]
      })
    ]
  }
})
// vite.config.js
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      resolvers: [ElementPlusResolver()]
    }),
    Components({
      resolvers: [ElementPlusResolver()]
    })
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

回到目录…

9.2 加载字体图标

在这里插入图片描述

第一步:安装 icons 字体图标

npm install @element-plus/icons-vue

第二步:全局注册,创建 src/plugins/icons.js 文件,添加以下内容

import * as components from "@element-plus/icons-vue";
export default {
    install: (app) => {
        for (const key in components) {
            const componentConfig = components[key];
            app.component(componentConfig.name, componentConfig);
        }
    }
};

第三步:引入文件,在 main.js 中引入 icons.js 文件

import elementIcon from "./plugins/icons"
createApp(App).use(elementIcon).mount('#app')

第四步:直接复制代码即可

<el-icon><CirclePlus /></el-icon>

回到目录…


总结:
提示:这里对文章进行总结:
本文是对Vue的学习,学习了Vue的选项式API和组合式API,组件之间的交互,引入swiper第三方插件,网络请求封装,还有Router路由,Vuex状态管理,加载Element-plus组件。之后的学习内容将持续更新!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue3 详细教程 的相关文章

随机推荐

  • 【Educoder python 作业答案】国防科技大学《大学计算机基础》冯·诺依曼体系结构模拟机 TOY2

    Educoder python 作业答案 国防科技大学 大学计算机基础 冯 诺依曼体系结构模拟机 TOY2 第1关 TOY2 计算机建模与模拟 第2关 外置函数numpy 科学计算工具 第3关 函数正确调用 得到想要的结果 第4关 函数与函
  • MQTT 控制报文 - PUBLISH发布消息,PUBACK,PUBREC,PUBREL,PUBCOMP - 第6章

    目录 6 1 PUBLISH 发布消息 6 1 1 固定报头 6 1 1 1 DUP重发标志 6 1 1 2 Qos服务质量等级 6 1 1 3 RETAIN保留标志 6 1 2 可变报头 6 1 3 有效载荷 6 2 PUBACK 发布确
  • 使用虚拟机遇到的一次问题——虚拟机ping不通网关

    问题 主机可以ping到虚拟机 外网 虚拟机可以ping到圆环地址 可以ping到同网段下其他虚拟机 虚拟机ping不到网关 ping不到外网 检查了网络编辑器的设置 没有问题 主机ipconfig发现问题 默认网关没了 进入属性编辑器添加
  • JS事件高级

    1 注册事件 绑定事件 1 1 注册事件概述 给元素添加事件 称为注册事件或者绑定事件 注册事件有两种方式 传统方式和方法监听注册方式 传统注册事件 利用on开头的事件onclick
  • JAVA接收JSON中的数组

    入参数据示例 respCode 0000 respMsg 请求成功 bizSeqNo 22022120001184432418054888526616 transTime 20220221180548 success true tokenA
  • 思科视频会议系统+服务器,Cisco思科MCU5310视频会议系统服务器

    业界 的高清MCU Cisco 5300系列MCU Cisco 5300系列系列MCU 为目前业界 的一款全高清MCU产品 具备高度稳定性 可管理性 同时具有灵活的容量端口数 能充分满足用户需求 一 的稳定性 灵活的端口容量 Cisco53
  • 华为OD机试 Python 矩阵稀疏扫描

    描述 题目描述 一个矩阵 如果其中大部分元素都是0 我们就称它为 稀疏矩阵 稀疏矩阵在实际应用中很常见 处理这种矩阵可以大大提高计算效率 现在 你得到了一个矩阵 要求你检查哪些行和列是 稀疏 的 稀疏 的定义是 当一个行或列中的0的数量超过
  • jQuery的ajaxform()

    https blog csdn net qq 38602656 article details 78668924 https blog csdn net weixin 41355260 article details 79851651
  • Linux系统中修改Oracle数据库字符编码集

    具体操作步骤如下 su oracle sqlplus nolog connect as sysdba 查看数据库字符编码集 select userenv language from dual shutdown immediate start
  • mysql中00933错误_java.sql.SQLException: ORA-00933: SQL 命令未正确结束错误解决

    在程序运行时 程序报sql错误 nested exception is java sql SQLException ORA 00933 SQL 命令未正确结束 具体错误如下所示 调用函数异常 org springframework jdbc
  • 性价比较高的笔记本电脑推荐

    推荐一 联想小新Air14锐龙版 优点 6核处理器 Zen2架构 性能释放高达26w 高色域屏幕 支持DC调光 硬盘扩展性好 双M 2插槽 有USB C接口 支持PD充电 缺点 单USB C接口 充电时占用接口 推荐二 惠普 ZBook S
  • antDv 级联选择器(a-cascader)通过接口动态加载数据

    每次子选择器的内容都是通过将父级id传给接口获取到 最终保存到data中参数selectItem格式为 xxx xx x
  • 计算机网络与服务器

    目录 架构体系及相关知识 三层架构 四层架构 常见的应用的模式 OSI模型 分层 数据链路层 TCP IP模型 TCP和UDP都是传输层的协议 TCP三次握手 四次次分手 URL HTTP协议详解 网址URL 结构化 报文行 报文头 空行
  • (G)ZS-CMR数据划分

    G ZS CMR 即 广义 零样本跨模态检索 设置类比 广义 零样本学习 G ZSL 这里记录两种划分 不限 CMR 也可以是 image retrieval ZS CMR 参考 1 类比 ZSL 整个数据集先从 class 角度分 see
  • 【java基础】java关键字总结及详解

    Java关键字是电脑语言里事先定义的 有特别意义的标识符 有时又叫保留字 还有特别意义的变量 Java的关键字对Java的编译器有特殊的意义 他们用来表示一种数据类型 或者表示程序的结构等 关键字不能用作变量名 方法名 类名 包名和参数 一
  • “应用程序配置不正确,应用程序未能启动” 错误的解决

    转载自 http hi baidu com xunxun129 blog item 6b311ccf24f4900992457e87 html 一 问题描述 今天在虚拟机上装了XP系统 但运行一个win32 Console程序时弹出对话框
  • 【第八章 IDEA中常用快捷键】

    第八章 IDEA中常用快捷键 1 Ctrl Y 删除光标所在行的所有内容 Ctrl X也可以 2 Ctrl D 快速向下复制当前行的内容 3 Ctrl W 递进式选中代码 可以先选中光标所在的一部分代码 连续按这个快捷键会在原来的基础上继续
  • 3dsmax子菜单无法选择_超全!!3ds Max重要的快捷键指令都在这里!画图速度提高一倍...

    室内设计胶囊 每个人都在努力的学习 感觉自己有一段时间没有练习了 只是偶尔工作的时候用用 大家都在努力 那我也出一点点力量吧 有同学说3ds Max 里面的快捷键实在太多了 全部记住有些吃力 能不能整理一份重要的 常用的快捷键 这样在记忆的
  • 史上最全 Vue 前端代码风格指南

    这篇文章是在公众号JS每日一题里抄过来的 觉得有用 收藏在这里 一 命名规范 市面上常用的命名规范 camelCase 小驼峰式命名法 首字母小写 PascalCase 大驼峰式命名法 首字母大写 kebab case 短横线连接式 Sna
  • Vue3 详细教程

    文章目录 一 API 风格 1 1 选项式 API 1 2 组合式 API 二 Vue 指令 2 1 文本插值 2 2 v html 标签元素 2 3 v on 绑定事件 2 4 v show 隐藏元素 2 5 v if 消除元素 2 6