Vue3用法

文章目录

  • Vue3
    • 1.创建vue3
      • 1.1 使用vue-cli创建
      • 1.2 使用vite创建(node版本>12.0.0.0)
    • 2.setup函数
    • 3.ref函数(修改数据需要.value)
    • 4.reactive函数(对象类型数据)
    • 5.setup参数
      • props传参
      • context参数
    • 6.computed计算属性
    • 7.watch监听
    • 8.watchEffect监听(一进来就触发)
    • 9.生命周期钩子函数
    • 10.hook
    • 11.toRef
    • 12.toRefs
    • 13.Router路由跳转与传参
    • 14.在vuex中的用法
    • 15.对于TypeScript的支持
    • 其他组合式api
      • 1.shallowReactive与shallowRef
      • 2.readyonly与shallowReadyonly
      • 3.toRaw与markRaw
      • 4.provide与inject
    • 响应式数据判断
    • Teleport(传送) 重点!!
    • Suspense与异步组件
  • vue3与vue2区别
    • 1. 根组件挂载(入口文件main.js)
    • 2. vue3组件中模板结构可以没有根标签
    • 3.1 vue2数据响应式原理
    • 3.2 vue3数据响应式原理
  • Vue3全局api
  • Vue3挂载全局axios
  • 工具库简单使用
    • mock.js模拟数据
  • 配置请求代理解决跨域
  • vue3使用script setup 语法糖
  • pinia 状态管理
    • 安装
    • 示例

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 标签需要是 <%= htmlWebpackPlugin.options.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 中 

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传参


context参数

//父组件




//子组件



6.computed计算属性




7.watch监听

//与vue2的watch配置功能一致
两个坑:
    监听reactive的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)
    监听reactive定义的响应式数据中某个属性时:deep配置有效



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




9.生命周期钩子函数

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

10.hook

本质上是一个函数,把setup函数中使用得组合式api进行了封装
类似于vue2中得mixin
使用:


//在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



12.toRefs



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(浅只读)


应用场景:接收别人组件传过来的值,使用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(传送) 重点!!

传送,可以打破多级组件,直接定位到目标结构
 // 将该结构直接移动到对应得结构中,比如body,htl等

我是一个弹窗

Suspense与异步组件

Suspense :等待异步组件时渲染一些额外的内容,增强用户体验
//异步引入组件



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修饰符
父组件中绑定事件

子组件中声明自定义事件

3.移除了filter过滤器 (官方推荐使用computed与methods来使用函数处理)
示例:
第一种用computed实现




第二种使用methods实现




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 语法糖



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




你可能感兴趣的:(vue,前端,vue)