Vue3用法

Vue3

1.创建vue3

1.1 使用vue-cli创建

vue ui    
或者 vue create project

1.2 使用vite创建(node版本>12.0.0.0)

兼容注意:必须安装Volar插件 ,使用vscode

安装vite
npm init vite@latest
或者
npm init @vitejs/app
//安装vite同时创建vite项目
npm init vite@latest my-vue-app --template vue
//vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import {loadEnv}from 'vite'
import path from "path";
 
export default defineConfig({
  plugins: [vue()],
  base: "./", // 类似publicPath,'./'避免打包访问后空白页面,要加上,不然线上也访问不了
  mode:"",//设置开发模式还是生成模式
  server: {
    https: false, // 是否开启 https
    open: false, // 是否自动在浏览器打开
    host: "127.0.0.1",//域名
    port: 3000, // 端口号
    proxy: {
      "/api": {
        target: "", // 后台接口
        changeOrigin: true,//跨域处理
        secure: false, // 如果是https接口,需要配置这个参数
        // ws: true, //websocket支持
        rewrite: (path) => path.replace(/^\/api/, ""),
      },
    },
  resolve: {
    alias: {
      // 如果报错__dirname找不到,需要安装node,执行npm install @types/node --save-dev
      "@": path.resolve(__dirname, "src"),      
      "@assets": path.resolve(__dirname, "src/assets"),
      "@components": path.resolve(__dirname, "src/components"),
      "@images": path.resolve(__dirname, "src/assets/images"),
      "@views": path.resolve(__dirname, "src/views"),
      "@store": path.resolve(__dirname, "src/store"),
    },
  },
 /*
  build: {
    outDir: "dist",
    // 9月更新
    assetsDir: "assets", //指定静态资源存放路径
    sourcemap: false, //是否构建source map 文件
    terserOptions: {
      // 生产环境移除console
      compress: {
        drop_console: true,
        drop_debugger: true,
      },
    },
  },
 */

  },
  // 引入第三方的配置
  optimizeDeps: {
  //include: ["element-plus/lib/locale/lang/zh-cn"],//举例
  },
});
// Vue.config.js 配置选项
module.exports = {
    // 选项
    
    //  基本路径
    publicPath: "./",

    //  构建时的输出目录
    outputDir: "dist",

    //  放置静态资源的目录
    assetsDir: "static",

    //  html 的输出路径
    indexPath: "index.html",

    //文件名哈希
    filenameHashing: true,

    //用于多页配置,默认是 undefined
    pages: {
        index: {

            // page 的入口文件
            entry: 'src/index/main.js',

            // 模板文件
            template: 'public/index.html',

            // 在 dist/index.html 的输出文件
            filename: 'index.html',

            // 当使用页面 title 选项时,
            // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
            title: 'Index Page',

            // 在这个页面中包含的块,默认情况下会包含
            // 提取出来的通用 chunk 和 vendor chunk。
            chunks: ['chunk-vendors', 'chunk-common', 'index']

        },
        // 当使用只有入口的字符串格式时,
        // 模板文件默认是 `public/subpage.html`
        // 如果不存在,就回退到 `public/index.html`。
        // 输出文件默认是 `subpage.html`。
        subpage: 'src/subpage/main.js'
    },

    //  是否在保存的时候使用 `eslint-loader` 进行检查。
    lintOnSave: true,

    //  是否使用带有浏览器内编译器的完整构建版本
    runtimeCompiler: false,

    //  babel-loader 默认会跳过 node_modules 依赖。
    transpileDependencies: [ /* string or regex */ ],

    //  是否为生产环境构建生成 source map?
    productionSourceMap: true,

    //  设置生成的 HTML 中 <link rel="stylesheet"> 和 <script> 标签的 crossorigin 属性。
    crossorigin: "",

    //  在生成的 HTML 中的 <link rel="stylesheet"> 和 <script> 标签上启用 Subresource Integrity (SRI)。
    integrity: false,

    //  调整内部的 webpack 配置
    configureWebpack: () => {}, //(Object | Function)
    chainWebpack: () => {},

    // 配置 webpack-dev-server 行为。
    devServer: {
        open: process.platform === 'darwin', //配置自动启动浏览器
        host: '0.0.0.0',
        port: 8080,
        https: false,
        hotOnly: false // 热更新
        // 查阅 https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli/cli-service.md#配置代理
        proxy: {
            '/api': {
                target: "http://app.rmsdmedia.com",
                changeOrigin: true,
                secure: false,
                pathRewrite: {
                    "^/api": ""
                }
            },
            '/foo': {
                target: '<other_url>'
            }
        }, // string | Object
        before: app => {}
    },

    // CSS 相关选项
    css: {

        // 将组件内的 CSS 提取到一个单独的 CSS 文件 (只用在生产环境中)
        // 也可以是一个传递给 `extract-text-webpack-plugin` 的选项对象
        extract: true,

        // 是否开启 CSS source map?
        sourceMap: false,

        // 为预处理器的 loader 传递自定义选项。比如传递给
        // Css-loader 时,使用 `{ Css: { ... } }`。
        loaderOptions: {
            css: {
                // 这里的选项会传递给 css-loader
            },
            postcss: {
                // 这里的选项会传递给 postcss-loader
            }
        },
        // 为所有的 CSS 及其预处理文件开启 CSS Modules。
        // 这个选项不会影响 `*.vue` 文件。
        modules: false
    },

    // 在生产环境下为 Babel 和 TypeScript 使用 `thread-loader`
    // 在多核机器下会默认开启。
    parallel: require('os').cpus().length > 1,
        
    // PWA 插件的选项。
    // 查阅 https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli-plugin-pwa/README.md
    pwa: {},

    // 三方插件的选项
    pluginOptions: {
        // ...
    }
}

2.setup函数

组件中所用到的:数据  方法等,均需配置在setup中
1.返回一个对象,则对象中的属性,方法,在模板中可以直接使用(常用)
2.返回一个渲染函数,则可以自定义渲染内容
//注意点:
setup不能是一个async函数,因为返回值不再是return的对象,而是proise,模板中看不到reutrn对象中的熟悉。(注意:后期也可以返回一个promise实例,但是需要Suspense与异步组件(defineAsyncComponents)的配合)

<template>
<h1>一个人的信息</h1>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @clcik="sayHello">sayHello</button>
</template>

<script>
setup(){
    let name='zs',
    let age=18
    function sayHello(){
        alert(`我叫${name},我${age}岁了!`)
    }
    
    return {  //返回一个对象
        name,
        age,
        sayHello
    }
}
</script>

3.ref函数(修改数据需要.value)

//引入ref函数
import { ref } from "vue";
setup() {
    let name = ref("zs");  //响应式数据 ref()
    let job=ref({
      type:"前端工程师",
      salary:"30k"
    })
    function sayhi() {
      alert("zs");
    }
    function changeInfo() {
   name.value='ls',
   job.value.type="java工程师",  //修改属性值 需要.value(因为是一个引用实现对象  基本数据类型使用的ref(数据劫持), 对象类型求助了vue内部的reactive函数(proxy)
   job.value.salary="40k"
      console.log(name);
    }
    return {
      name,
      job,
      sayhi,
      changeInfo,
    };
  },

4.reactive函数(对象类型数据)

import {reactive} from 'vue'
setup(){
// const 对象=reactive({})        返回一个proxy的代理对象
    let person =reactive({             //使用reactive函数可以使对象形式的数据变成响应式
         name:'zs',
         age:18,
         job:{
              type:'前端开发',
             salary:"30k",
         }       
     })
     let hobby=reactive(['抽烟''喝酒''打麻将'])  
     function changeInfo(){
         person.name='ls',
         person.age=30,
         person.job.type='后端开发',
         person.job.salary='40k'
         hobby[0]='学习'
     }  
    return {
          person,   //返回一个代理对象(proxy代理的实例对象)
           changeInfo
    }
}

5.setup参数

props传参

<script>
export default{
props:['msg'],
setup(props){
console.log(props)
}
}
</script>

context参数

//父组件
<template>
 <home @hello='showx' msg='你好' school='家里蹲大学'></home>
 <template #qwe>    //具名插槽   #qwe可以写成v-slot:qwe
     <h3>你好啊哥哥们</h3>
   </template>
</template>

<script>
import home from './components/home.vue'
export default {
components:{
  home
},
setup(){
  function showx(value){
    console.log('99');
    alert(`你好,你触发了hello事件,我收到的参数是${value}`)
  }

  return{
    showx
  }
}

};
</script>

//子组件
<template>
 <button @click="handclick">测试触发一下父组件的hello事件</button>
<slot name="qwe"></slot>   //具名插槽使用
</template>

<script>
export default{
props:['msg'],
emits:['hello'], //需要通知一下,否则会有警告(不影响使用)
setup(context){
console.log(context)  
    // context参数:attrs 获取当前组件上所有得属性得对象,props未声明得会到这里显示;slots;emit
    // 触发父组件
    function handclick() {
      context.emit('hello',999)
    }

     return {
      handclick,
    };
}
}
</script>

6.computed计算属性

<template>
<div>
  <h1>一个人的信息</h1>
  姓:<input type="text" v-model="person.firstName">
  <br>
  名:<input type="text" v-model="person.lastName">
  <br>
  <span>全名:{{person.fullName}}</span>
  </div>
</template>

<script>
import { reactive ,computed} from "vue"; //引入计算属性computed
export default {
  name: "test",
// computed:{  //vue2写法(简写
//     // 计算属性可以直接用
//     fullName(){
//         return this.person.firstName+'-'+this.person.lastName
//     }
// },
  setup() {
    let person = reactive({
      firstName: "张",
      lastName: "三",
    })
//计算属性--简写(未考虑可修改)
person.fullName=computed(()=>{
    return person.firstName+'-'+person.lastName
})
 //计算属性--完整写法(可读可改)  
      person.fullName=computed({
  get(){
        return person.firstName+'-'+person.lastName
  }
  set(value){
        const  nameArr=value.split('-')     
        person.firstName=nameArr[0]
        person.lastName=nameArr[1]
  }
})
    return {
      person,
      //fullName
    };
  },
};
</script>

7.watch监听

//与vue2的watch配置功能一致
两个坑:
    监听reactive的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)
    监听reactive定义的响应式数据中某个属性时:deep配置有效
<template>
<h2>当前求和为:{{sum}}</h2>
<button @click="sum++">点我加1</button>
<h2>当前的信息为:{{msg}}</h2>
<button @click="msg+='!'">修改信息</button>

<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="person.name+='~'">修改信息</button>
<button @click="person.age++">修改信息</button>
</template>

<script>
    //引入watch监听函数
import { ref,reactive,watch} from "vue";

export default {
  setup() {
let sum=ref(0)
let msg=ref('你好啊')
let person=reactive({
    name:'zs',
    age:30
})
// 1.监视基本类型数据-多个
watch([sum,msg],(newVlaue,oldValue)=>{   //三个参数,第一个监听对象,第二个回调函数,第三个配置项如{immediate:true,deep:true} 可以在开始时候就监听
    console.log('sum或msg变了',newVlaue,oldValue);
},{immediate:true})
// 2.监听基本类型数据-单个
 watch(msg,(newVlaue,oldValue)=>{
    console.log('msg变了',newVlaue,oldValue);
})
// 3.监听reactive所定义的对象类型数据
 watch(person,(newVlaue,oldValue)=>{
     console.log('person变了',newVlaue,oldValue);//oldValue值也变了,目前是vue3中的bug
 })
// 4. 监视reactive所定义的一个响应式数据中的某个属性
watch(()=>person.age,(newVlaue,oldValue)=>{
    console.log('person.age变化了',newVlaue,oldValue);
})
// 5.监视reactive所定义的一个响应式数据中的某些属性(推荐s函数表达式方式监听对象的值
watch([()=>person.age,()=>person.name],(newVlaue,oldValue)=>{
    console.log('person.age或者name变化了',newVlaue,oldValue);
})
//特殊情况:监听reactive所定义的对象数据中的某个对象或者更深层的数据时
watch(()=>person.job,(newValue,oldValue)=>{
    console.log('person.job变化了',newValue,oldValue)
},{deep:true})//需要开启深度监听
// 返回一个对象(常用)
    return {
      sum,
      msg,
      person
    }
  },
};
</script>

8.watchEffect监听(一进来就触发)

<template>
    <h2>当前求和为:{{ sum }}</h2>
    <button @click="sum++">点我加1</button>

    <h2>当前的信息为:{{ msg }}</h2>
    <button @click="msg += '!'">修改信息</button>

    <h2>姓名:{{ person.name }}</h2>
    <h2>年龄:{{ person.age }}</h2>
    <h2>薪资:{{ person.job.j1.salary }}K</h2>
    <button @click="person.name += '~'">修改姓名</button>
    <button @click="person.age++">增长年龄</button>
    <button @click="person.job.j1.salary++">增长薪资</button>
</template>
<script>
import { ref, reactive,watchEffect } from "vue";
export default {
    setup() {
        let sum = ref(0)
        let msg = ref('你好啊')
        let person = reactive({
            name: '张三',
            age: 19,
            job: {
                j1: {
                    salary: 30
                }
            }
        })
        //不指明监视哪个属性,监视的回调中用到哪个属性,就监视哪个属性
        watchEffect(() => {
            const x1 = sum.value     //监视sum的值
            const x2=person.job.j1.salary   //监视salary
            console.log('watchEffect监听了');
        })

        // 返回一个对象(常用)
        return {
            sum,
            msg,
            person

        }
    },
};
</script>

9.生命周期钩子函数

//两种方式:
 第一种与vue2一样,作为配置项来写(beforeDestroy-->beforeUnmount  destroyed-->unmounted)
 第二种写在setup中(组合式api形式书写)
 beforeCreate==>setup()
 created==>setup()
 其余的钩子全部带on前缀
写法: onMounted(()=>{})

10.hook

本质上是一个函数,把setup函数中使用得组合式api进行了封装
类似于vue2中得mixin
使用:
<template>
    <h2>当前求和为:{{ sum }}</h2>
    <button @click="sum++">点我加1</button>
    <hr>
    <h2>当前点击时鼠标得坐标为:x:{{point.x}}   y:{{point.y}}</h2>
</template>
<script>
import { ref } from "vue";
import usePoint from '@/hooks/usePoint'   //引入hooks中封装的函数
export default {
    setup() {
        let sum = ref(0);     
        let point =usePoint()   //调用hooks中得函数
        console.log(point);
        // 返回一个对象(常用)
        return {
            sum,
            point
        };
    },
};
</script>
//在src下创建hook文件夹 -》创建usePoint.js(封装hooks函数
import { reactive,onMounted,onBeforeUnmount } from "vue"
export default function savePoint() {
    //实现鼠标“打点”相关得数据
    let point = reactive({
        x: 0,
        y: 0
    })
    //实现鼠标“打点”相关得方法
    function savePoint(e) {
        console.log(e.pageX, e.pageY)
        point.x = e.pageX
        point.y = e.pageY
    }
     //实现鼠标“打点”相关得钩子
    onMounted(() => {
        window.addEventListener('click', savePoint)
    })
    onBeforeUnmount(() => {
        window.removeEventListener('click', savePoint)
    })
    return point
}

11.toRef

<template>
<h3>{{name2}}</h3>
<h3>{{salary}}</h3>
  <h2>姓名:{{ person.name }}</h2>
  <h2>年龄:{{ person.age }}</h2>
  <h2>薪资:{{ person.job.j1.salary }}K</h2>
  <button @click="person.name += '~'">修改姓名</button>
  <button @click="person.age++">增长年龄</button>
  <button @click="person.job.j1.salary++">增长薪资</button>
</template>
<script>
import { reactive,toRef} from "vue";
export default {
  setup() {
      let person = reactive({
          name: '张三',
          age: 19,
          job: {
              j1: {
                  salary: 30
              }
          }
      })
      // 返回一个对象(常用)
      return {
           person,
           name2:toRef(person,'name')//使用toRef指向person对象(类似于深拷贝
          salary:toRef(person.job.j1,'salary')
      }
}}
</script>

12.toRefs

<template>
  <h2>姓名:{{ name }}</h2>
  <h2>年龄:{{ age }}</h2>
  <h2>薪资:{{ job.j1.salary }}K</h2>
  <button @click="person.name += '~'">修改姓名</button>
  <button @click="person.age++">增长年龄</button>
  <button @click="person.job.j1.salary++">增长薪资</button>
</template>
<script>
import { reactive,toRefs} from "vue";
export default {
  setup() {
      let person = reactive({
          name: '张三',
          age: 19,
          job: {
              j1: {
                  salary: 30
              }
          }
      })
      // 返回一个对象(常用)
      return {
           person,
          ...toRefs(person)   //使用toRefs可以得到整个对象(类似于深拷贝数据
      }
}}
</script>

13.Router路由跳转与传参

方式1
import { useRouter } from 'vue-router';
export default {
  setup() {
    const router = useRouter();
    function goto(){
      router.push("/about");
    }
    return{
       goto  //一定要要放在return里才能在模板上面使用
    }
  }
}

方式2
import router from "../../router/index.js";
router.push("/");

路由传参
import router from "../../router/index";
 router.push({path:'/addShop',query:{id:id}})
//在其他页面获取这个传参
router.currentRoute._rawValue.query.id

14.在vuex中的用法

import { useStore } from 'vuex'
export default defineComponent({
    setup() {
    const store = useStore()
    const count = store.state.count;
    return {
        count,
    }
  }
})

15.对于TypeScript的支持

//列表定义的数据
interface Applet {
  id?: number;
  code: string;
  createAt: String,
  logo: string,
  merchantName: string,
  name: string;
  serviceName: string;
  tag: string;
  tagId: string;
}
 
const appletData = ref<Array<Applet>>([]);

//返回值 data中的值定义
interface AppletListResponse {
  count: number;
  list: Array<Applet>;
  page: number | string;
  pageSize: number | string;
}
 
//列表返回的值定义
interface AppletListRes {
  code: number;
  msg: string;
  data: AppletListResponse;
}
 
appletList(params).then((res: AppletListRes) => {
  if (res.code === 0) {
    appletData.value = res.data.list;
    total.value = res.data.count;
  }
});

//参数
interface AppletParams {
  page: number | string;
  pageSize: number | string;
  name?: string;
  storeName?: string;
  serviceName?: string;
  tag?: string;
}
 
//接口请求
export const appletList = (params: AppletParams): Promise<AppletListRes> => {
  return Http.get("/applet/list", params);
};

其他组合式api

1.shallowReactive与shallowRef

shalolowReactive  只考虑对象的第一层数据(浅响应式)
shallowRef       只能处理基本类型数据响应式

2.readyonly与shallowReadyonly

//禁止修改数据
readyonly(深只读)    shallowReadyonly(浅只读)
<template>
<h1>{{sum}}</h1>
  <h2>姓名:{{ name }}</h2>
  <h2>年龄:{{ age }}</h2>
  <h2>薪资:{{ job.j1.salary }}K</h2>
  <button @click="sum++">sum++</button>
  <button @click="name += '~'">修改姓名</button>
  <button @click="age++">增长年龄</button>
  <button @click="job.j1.salary++">增长薪资</button>
</template>
<script>
import {ref, reactive,toRefs,readonly,shallowReadonly} from "vue";
export default {
  setup() {
let sum=ref(0)
    let person = reactive({
      name: '张三',
      age: 19,
      job: {
        j1: {
          salary: 30
        }
      }
    })

// person=readonly(person)
person=shallowReadonly(person)
// sum=readonly(sum)
sum=shallowReadonly(sum)
    // 返回一个对象(常用)
    return {
         sum,
         ...toRefs(person)
    }

  }
}
</script>
应用场景:接收别人组件传过来的值,使用readyonly进行保护,操作结果来的值不会影响别人页面

3.toRaw与markRaw

toRaw将reactive生成的响应式数据对象还原成普通对象
使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的操作不会引起页面更新
markRaw:标记一个对象,使其永远不会再成为响应式对象(常用)
应用场景:1.有些之不应被设置为响应式的,例如复杂的第三方类库等
         2.当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能

4.provide与inject

使用:
//祖组件
let car=reactive({
  name:'奔驰',
  price:'40w'
})
provide('car',car)
//后代组件
let car= inject("car");
return{car}//记得需要return出去

响应式数据判断

isRef:检查一个值是否为一个ref对象
isReactive:检查一个对象是否由reactive创建的响应式代理
isReadonly:检查一个对象是否由readyonly创建的只读代理
isPoxy:检查一个对象是否由reactive或者readonly方法创建的代理

Teleport(传送) 重点!!

传送,可以打破多级组件,直接定位到目标结构
<teleport to="移动位置"> // 将该结构直接移动到对应得结构中,比如body,htl等
<div v-if="isShow" class="mask">
   <div class="dialog">
        <h3>我是一个弹窗</h3>
    </div>
    </div>
</teleport>

Suspense与异步组件

Suspense :等待异步组件时渲染一些额外的内容,增强用户体验
//异步引入组件
<template>
<div class="son">
    <h1>son</h1>
    <Suspense>  //使用Suspense包裹组件,并配置好default和fallback
        <template  v-slot:default>//在该插槽中使用组件
            <Child></Child>
        </template>
        <template  v-slot:fallback>//组件加载前的结构
         <h3>加载中</h3>
        </template>
    </Suspense>
</div>
</template>
<script>
import {defineAsyncComponent} from 'vue'
const Child =defineAsyncComponent(()=>import('./components/child.vue'))
</script>

vue3与vue2区别

1. 根组件挂载(入口文件main.js)

//引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import {createApp} from 'vue'
import App from './App.vue'
//创建应用实例对象----app(类似于之前的vue2中的vm,但app比vm更'轻'
const app = createApp(App)
//挂载
app.mount('#app')
/*
//vue2挂载方法
const vm= new Vue({
render:h=>h(App)
})
vm.$mount('#app')*/

2. vue3组件中模板结构可以没有根标签

3.1 vue2数据响应式原理

<html>
    ...
 <body>
 <script>
    let person={
     name:"zs",
     age:18
}

//模拟Vue2中实现响应式
let p={}
//正常是需要循环遍历key的
 Object.defineProperty(p,'age',{         //数据劫持
     configurable:true  //可配置的
     get(){
         return person.age
     },
     set(value){
         console.log('有人修改了age属性,我发现了,我要去更新页面了')
         person.age=value
     }
})   
 </script>
 </body>
</html>

3.2 vue3数据响应式原理

通过Proxy(代理):拦截对象中任意属性的变化,增删改查
通过Reflect(反射):对(源对象)被代理对象的属性进行操作

<html>
    ...
    <body>
 <script>
    let person={
     name:"zs",
     age:18
}

//模拟Vue3中实现响应式                 基于Es6的proxy代理
const p=new Proxy(person,{
    //有人读取p的某个属性时调用
    get(target,propName){
      console.log(`有人读取了p身上的${propName}属性`)
    //return target[propName]
        return Reflect.get(target,propName)  //reflect反射对象
   },
      //有人修改p的某个属性、或给p追加某个属性时调用
    set(target,propName,value){
        console.log(`有人修改了p身上的${propName}属性,我要去需修改界面了`)
       // target[propName]=value    
        return Reflect.set(target,propName,value)
  }, 
      //有人删除p的某个属性时调用
     deleteProperty(target,propName){
        console.log(`有人删除了p身上的${propName}属性,我要去需修改界面了`)
        //return delete taraget[propName]
         return Reflect.deleteProperty(target,propName)
     }
})
 </script>
 </body>
</html>

Vue3全局api


2.x全局api(Vue)              3.x实例api(app)

vue.config.xxx ----->        app.config.xxxx
Vue.config.productionTip     //vue3中移除
Vue.component  ----->        app.component
Vue.directive  ----->        app.directive
Vue.mixin      ----->        app.mixin
Vue.use        ----->        app.use
Vue.prototype  ----->        app.config.globalProperties

1.移除了keyCode作为v-on的修饰符,同时也不再支持config.keyCodes
2.移除了v-on.native修饰符
父组件中绑定事件
<my-component v-on:close="handleClose" v-on:Click="handleClick" />
子组件中声明自定义事件
<script>
  export default{
     emits:['close']
  }
</script>
3.移除了filter过滤器 (官方推荐使用computed与methods来使用函数处理)
示例:
第一种用computed实现
<template>
  <div id="app">
    <ul v-for="(item, index) in arr" :key="index">
      <li>快递公司:{{ item.deliverCompany }}</li>
      <!-- 使用计算属性 -->
      <li>运输状态:{{ computedText(item.expressState) }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  // data ...... 篇幅有限直接省略掉
  computed: {
    computedText() {
      // 计算属性要return一个函数接收参数            
      return function (state) {
        switch (state) {
          case "1":
            return "待发货";
            break;
          case "2":
            return "已发货";
            break;
          case "3":
            return "运输中";
            break;
          case "4":
            return "派件中";
            break;
          case "5":
            return "已收货";
            break;
          default:
            return "快递信息丢失";
            break;
        }
      };
    },
  },
};
</script>

第二种使用methods实现
<template>
  <div id="app">
    <ul v-for="(item, index) in arr" :key="index">
      <li>快递公司:{{ item.deliverCompany }}</li>
      <!-- 使用方法 -->
      <li>运输状态:{{ methodsText(item.expressState) }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  // data ...... 篇幅有限直接省略掉
  methods: {
    methodsText(state) {
      switch (state) {
        case "1":
          return "待发货";
          break;
        case "2":
          return "已发货";
          break;
        case "3":
          return "运输中";
          break;
        case "4":
          return "派件中";
          break;
        case "5":
          return "已收货";
          break;
        default:
          return "快递信息丢失";
          break;
      }
    },
  },
};
</script>

Vue3挂载全局axios

第一种方案
//在main.js中写入
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
const app = createApp(App)
app.config.globalProperties.$http = axios//全局挂载
//组件中使用
vue3.0中是没有this的。使用getCurrentInstance来获取上下文
//getCurrentInstance() 获取全局globalProperties 中配置的信息
const { proxy } = getCurrentInstance()// 这里的proxy相当于this
proxy.$http.get('api/getNewsList')
.then((response)=>{
    console.log(response)
})
第二种方案
二、使用vue-axios插件
//首先在主入口文件main.js中引用:
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App)
app.use(VueAxios,axios);
//然后在组件中引用,注意vue3.x没有this
axios.get('api/getNewsList')
.then((response)=>{
    console.log(response)
})

工具库简单使用

mock.js模拟数据

安装
npm i mockjs 
使用
import Mock from 'mockjs'
示例:
// 使用 Mock
1.直接定义数据
let dataSource = Mock.mock({
    'dataSource|5':[{
        'key|+1': 1,
        'mockTitle|1':['哑巴', 'Butter-fly', '肆无忌惮', '摩天大楼', '初学者'],
        'mockContent|1': ['你翻译不了我的声响', '数码宝贝主题曲', '摩天大楼太稀有', '像海浪撞破了山丘'],
        'mockAction|1': ['下载', '试听', '喜欢']
    }]
})
// 输出结果
console.log(dataSource);

2.模拟接口返回数据:
//第一步:在assets中创建mock.js
import Mock from 'mockjs'
Mock.mock('/meun', /post|get/i, {
  // /post|get/i 匹配post和get模式 也可以用'post'或'get'
  "ret":0,
  "data":
    {
      "mtime": "@datetime",//随机生成日期时间
      "score|1-800": 800,//随机生成1-800的数字
      "rank|1-100":  100,//随机生成1-100的数字
      "stars|1-5": 5,//随机生成1-5的数字
      "nickname": "@cname",//随机生成中文名字
    }
})
//第二步在main.js中引入
import './assets/mock'
//第三步使用接口
import axios from 'axios'
    axios({
      method:'get',
      url:'/meun'
    }).then((res)=>{
     console.log(res);
    })

数据模板定义规范:
三部分构成:属性名(name)、生成规则(rule)、属性值(value)
'name|rule':value

配置请求代理解决跨域

根目录下创建vite.config.js
module.exports= {
      proxy: {
        // 选项写法
        '/api': {
          target: 'https://pvp.qq.com/',  //此处为需要处理跨域的接口
          changeOrigin: true,  //需要配置
          rewrite: (path) => path.replace(/^\/api/, '')//重写地址
        },     
      } 
  }

vue3使用script setup 语法糖

<script setup>
    import {ref} from 'vue'
    import MyComponent from './MyComponent.vue'      //无需注册声明(注:导入需要加上.vue后缀,否则ts无法识别)
    const msg =ref("HELLO")
    const fn=()=>{
       console.log(msg)
    }
    //在<script setup>中必须使用defineProps与defineEmits来声明props和 emits
    const props=defineProps({
        foo:String,
        default:()=>{return '测试信息'}       //默认值
    })
    const emit = defineEmits(['change','delete'])
    //1.与普通的<script>比较,如果在组件内部使用,无需return
    //2.如果需要暴露给外部使用,需要使用:dinfineExpose    
    defineExpose({
        msg,
        fn
    })
</script>
<template>
//可以直接在模板中使用
<div @click="fn">{{msg}}</div>
     <MyComponent></MyComponent>// 可以直接在模板中使用定义的组件
</template>

pinia 状态管理

安装

npm i pinia@next
//src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
// 实例化 Vue
const app = createApp(App)
// 安装 Pinia
app.use(createPinia())
// 挂载在真实 DOM
app.mount('#app')
----------------------------------------------------------
    //若在vue2中使用  需要额外安装PiniaVuePlugin
import { createPinia, PiniaVuePlugin } from 'pinia'
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
new Vue({
  el: '#app',
  pinia,
})

示例

//src/store/modules/counter.ts
import {defineStore} from "pinia"
 
//使用前必须用difineStore()定义一个仓库
//方式一:
export const useCounterStore = defineStore("counter",{
  state:()=>{
    return {
      count:0
    }
  },
  actions:{
    increment(){
      this.count++
    }
  }
})
//方式二:使用类似setup()方式定义store
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  function increment() {
    count.value++
  }
  return { count, increment }
})

<template>
  <div>count:{{counter.count}}</div>
</template>
<script lang="ts" setup>
import { storeToRefs } from "pinia";
    //导入store
import { useCounterStore } from '@store/modules/counter';

const counter = useCounterStore();//接收store数据
    
// const {count}=counter // 注意: 直接解构会使变量失去响应式
const {count}=storeToRefs(counter)  

 //方式一:修改单一数据
counter.count++    
 //f修改多个数据 $patch批量更新
counter.$patch({count:counter.count+1}) 
// 方式三: $patch  一个函数,批量更新 (建议使用方式)
  // 这里传了一个函数
  // mainStore.$patch(state=>{
  //   state.count++
  // })
    counter.increment()
</script>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值