Vue3——渐进式框架

创建项目

vue create vue-demo

运行项目

第一步:进入项目根目录 cd vue-demo

第二步:运行 npm run serve 启动项目

安装Vue高亮插件:volar

模板语法

文本

数据绑定最常见的形式就是使用“Mustache” (双大括号) 语法的文本插值

<template>
  <div class="hello">
    <h3>学习Vue:模板语法</h3>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
      message: "爷不学了"
    }
  }
}
</script>

属性 Attribute

Mustache 语法不能在 HTML 属性中使用,然而,可以使用 v-bind指令

v-bind:id 可以简写成 :id

条件渲染

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true 值的时候被渲染。

v-else你可以使用 v-else 指令来表示 v-if 的“else 块”

v-show另一个用于条件性展示元素的选项是 v-show 指令

<p v-if="flag">flag为true才显示哦</p>
    <p v-else>flag为false才显示哦</p>
    <p v-show="flag">flag为true才显示哦</p>

列表渲染

v-for 把一个数组映射为一组元素

我们可以用 v-for 指令基于一个数组来渲染一个列表。 v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而item 则是被迭代的数组元素的别名

<ul>
      <li v-for="item in newLists" :key="item.id" @click="clickItemHandle(item.title)">
        {{ item.title }}
      </li>
    </ul>

newLists: [
        {
          id: 1001,
          title: "今日新闻1"
        },
        {
          id: 1002,
          title: "今日新闻2"
        },
        {
          id: 1003,
          title: "今日新闻3"
        }
      ]

事件处理

监听事件

我们可以使用 v-on 指令 (通常缩写为 @ 符号) 来监听 DOM 事件,并在触发事件时执行一些 JavaScript。用法为 v-on:click="methodName" 或使用快捷方式 @click="methodName"

事件处理方法

event接受调用对的方法名称

事件传递参数

表单输入绑定

.lazy修饰符

在默认情况下, v-model 在每次 input 事件触发后将输入框的值与数据进行同步 。你可以添加 lazy 修饰符,从而转为在 change 事件之后进行同步

.trim

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim修饰符

组件基础

单文件组件

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

加载组件

第一步:引入组件 import MyComponentVue from './components/MyComponent.vue'

第二步:挂载组件 components: { MyComponentVue }

第三步:显示组件 <my-componentVue />

Props组件交互

Prop 是你可以在组件上注册的一些自定义 attribute

//App.vue
<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <!-- <HelloWorld msg="Welcome to Your Vue.js App"/> -->
  <!-- <hello-world /> -->
  <MyComponent :title="title" :age="age" :names="names"/>
</template>

<script>
// import HelloWorld from './components/HelloWorld.vue'
import MyComponent from './components/MyComponent.vue';

export default {
  name: 'App',
  data(){
    return{
      title:"我是一个标题",
      age:26,
      names:['abc','cba','bac']
    }
  },
  components: {
    // HelloWorld,
    MyComponent
}
}
</script>

//MyComponent.vue
<template>
    <h3>prop传递数据</h3>
    <p>{{ title }}</p>
    <p>{{ age }}</p>
    <ul>
        <li v-for="(item,index) in names" :key="index">{{ item }}</li>
    </ul>
</template>

<script>
export default {
    name: "MyComponent",
    props: {
        title: {
            type: String,
            default: ""
        },
        age: {
            type: Number,
            default: 0
        },
        names:{
            type:Array,
            //数组和对象必须使用函数进行返回
            default:function(){
                return []
            }
        }
    }
}
</script>

自定义事件组件交互

自定义事件可以在组件中反向传递数据, prop 可以将数据从父组件传递到子组件,那么反向如何操作呢,就可以利用自定义事件实现$emit

组件生命周期

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

Axios网络请求

Axios 是一个基于 promise 的网络请求库

安装

Axios的应用是需要单独安装的 npm install --save axios

引入

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

全局引用:

import axios from "axios"
const app = createApp(App);
app.config.globalProperties.$axios = axios
app.mount('#app')
// 在组件中调用
this.$axios

网络请求基本示例

get请求

mounted() {
        console.log("mounted:组件渲染完成");
        // 把网络请求放到这里
        axios({
            method: "get",
            url: "http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php"
        }).then(
            res => {
                console.log(res.data);
                this.chengpin = res.data.chengpinDetails[0]
            }
        )
    },

post请求

post请求参数是需要额外处理的

1 安装依赖: npm install --save querystring

2 转换参数格式: qs.stringify({})

mounted() {
        console.log("mounted:组件渲染完成");
        // 把网络请求放到这里
        axios({
            method: "post",
            url: "http://iwenwiki.com/api/blueberrypai/login.php",
            data: QueryString.stringify({
                user_id: "iwen@qq.com",
                password: "iwen123",
                verification_code: "crfvw"
            })
        }).then(res => {
            console.log(res.data);
        })
        
    },

简洁版

Axios网络请求封装

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

src 目录下创建文件夹 utils ,并创建文件 request ,用来存储网络请求对象 axios

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

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

//拦截器
//发送数据之前
instance.interceptors.request.use(
    config => {
        if (config.methods === "post") {
            config.data = qs.stringify(config.data)
        }
        return config;
    },
    error => {
        return Promise.reject(error)
    }
)

//获取数据之前
instance.interceptors.response.use(
    response => {
        return response.status === 200 ? Promise.resolve(response) : Promise.reject(response)
    },
    error => {
        const { response } = error;
        errorHandle(response.status,response.info)
    }
)
export default instance;

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;
    }
}

src 目录下创建文件夹 api ,并创建文件 index path 分别用来存放网络请求方法和请求路径

//path.js
const base = {
    baseUrl:"http://iwenwiki.com/",
    chengpin:"api/blueberrypai/getChengpinDetails.php"
}
export default base;

//index.js
import axios from "../utils/request"
import path from "./path"

const api ={
    getChengpin(){
        return axios.get(path.baseUrl+path.chengpin)
    }
}
export default api

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

import api from "../api/index"
2
3 api.getChengpin().then(res =>{
4    console.log(res.data);
5 })

网络请求跨域解决方案

当协议、域名、端口任意一个不相同时,都会产生跨域问题,所以又应该如何解决跨域问题呢

//vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    proxy: {
      '/api': {
        target: 'http://iwenwiki.com/',
        changeOrigin: true
      }
    }
  }
})

//MyComponent.vue
// this.$axios.get("http://iwenwiki.com/api/FingerUnion/list.php")
        this.$axios.get("/api/FingerUnion/list.php")
        .then(res=>{
            console.log(res.data);
            console.log("此处应出现跨域错误");
        })

Vue引入路由配置

在Vue中,我们可以通过 vue-router 路由管理页面之间的关系

Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举

在Vue中引入路由

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

第二步:配置独立的路由文件

// router/index.js
import {createRouter, createWebHashHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'
// import AboutView from '../views/AboutView.vue'
const routes = [
    {
        path: '/',
        name: 'home',
        component: HomeView
    },
    {
        path: '/about',
        name: 'about',
        component: () =>
            import('../views/AboutView.vue')
    }
]
const router = createRouter({
    history: createWebHashHistory(),
    routes
})
export default router

路由传递参数

页面跳转过程中,是可以携带参数的,这也是很常见的业务

例如:在一个列表项,点击进入查看每个列表项的详情

嵌套路由配置

路由嵌套是非常常见的需求

第一步:创建子路由要加载显示的页面

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

{
    path: '/about',
    name: 'about',
    redirect:"/about/us",
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue'),
    children:[
      {
        path:'us',
        component:() => import('../views/AboutSub/AboutUs.vue')
      },
      {
        path:'info',
        component:() => import('../views/AboutSub/AboutInfo.vue')
      }
    ]
  },

第三步:指定子路由显示位置 <router-view></router-view>

第四步:添加子路由跳转链接

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <RouterLink to="/about/us">我们</RouterLink>|
    <RouterLink to="/about/info">信息</RouterLink>
    <router-view></router-view>
  </div>
</template>

第五步:重定向配置 redirect:"/news/baidu"

Vue状态管理(Vuex)

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

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

最常用的核心概念包含: State Getter Mutation Action

Getter

对Vuex中的数据进行过滤

//HomeView.vue
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <h3>home</h3>
    <!-- <p>counter={{ $store.getters.getCounter }}</p> -->
    <p>counter={{ getCounter }}</p>
  </div>
</template>

<script>
import{mapGetters} from 'vuex'

export default {
  name: 'HomeView',
  computed:{
    ...mapGetters(["getCounter"])
  }
}
</script>
//store/index.js
import { createStore } from 'vuex'

export default createStore({
  state: {
    counter:10
  },
  getters: {
    getCounter(state){
      return state.counter>0? state.counter:"counter数据异常"
    }
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

Mutation

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

Action

Action 类似于 mutation,不同在于:

Action 提交的是 mutation,而不是直接变更状态

Action 可以包含任意异步操作

  actions: {
    asyncAddCounter({commit}){
      axios.get("http://iwenwiki.com/api/generator/list.php")
      .then(res =>{
        commit("addCounter",res.data[0])
      })
    }
  },


 ...mapActions(["asyncAddCounter"]),
    addAsyncClickHandle(){
      // this.$store.dispatch("asyncAddCounter");
      this.asyncAddCounter();
    }

Vue3新特性

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

ref或者reactive

import { ref,reactive } from "vue"
export default {
  name: 'HelloWorld',
  setup(){
      const name = ref("iwen")
      const state = reactive({
          list:[]
     })
    return{
        name,
        state
   }
 }
}

methods中定义的方法写在setup()

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

setup() {
    const http = ()=>{
        // do something
   }
    return {
      http
   };
}

setup()中使用props和context

export default {
  props: {
    name: String,
 },
  setup(props,ctx) {
    console.log(props.name)
    ctx.emit('event')
 },
}

在setup中使生命周期函

你可以通过在生命周期钩子前面加上 “on” 来访问组件的生命周期钩子。

下表包含如何在 setup () 内部调用生命周期钩子

export default {
  setup() {
    // mounted
    onMounted(() => {
      console.log('Component is mounted!')
   })
 }
}
同一函数可重复使用

Provide / Inject

provide() 和 inject() 可以实现嵌套组件之间的数据传递。

这两个函数只能在 setup() 函数中使用。

父级组件中使用 provide() 函数向下传递数据。

子级组件中使用 inject() 获取上层传递过来的数据。

不限层级

// 父组件
import { provide } from "vue"
setup() {
    provide("customVal", "我是父组件向子组件传递
的值");
}
// 子组件
import { inject } from "vue"
setup() {
    const customVal = inject("customVal");
    return {
      customVal
   }
}

Fragment

不再限于模板中的单个根节点

Element-plus

安装Element-Plus

npm install element-plus --save

完整引用

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

按需导入

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

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

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

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

const { defineConfig } =require('@vue/cli-service')
constAutoImport=require('unplugin-auto-
import/webpack')
constComponents=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()]      })
    ]
  }
})

最后,可以直接在组件中使用,在百度搜索element找到官网复制代码即可。

Element-plus的字体图标

安装 icons 字体图标

npm install @element-plus/icons-vue

全局注册

在项目根目录下,创建 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";
app.use(elementIcon)

使用方式

接下来就可以直接在组件中引入使用了

<el-icon class="expand" color="#409EFC"
:size="30">
    <expand />
</el-icon>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值