vue3学习笔记速通

模板语法

{{ }}

动态绑定文本,可以在{{}}使用单个表达式

<template>
	<div>{{text}}</div>
	<div>{{num + 10}}</div>
	<div>{{flag ? "true" : "false"}}</div>	
</template>
<script>
export default {
    name: 'helloVue',
    data() {
        return {
            text: 'hello',
            num: 10,
            flag: true
        }
    }
}
</script>

v-html

动态绑定网页

<template>
	<div v-html="url"/>
</template>
<script>
export default {
    name: 'helloVue',
    data() {
        return {
            url: "<a href='http://www.xxx.com'>xxx</a>",
        }
    }
}
</script>

v-bind

动态绑定属性,可以简写成: <----> v-bind:

<template>
	<div v-bind:id="div1"/>
	<div :id="div2"/>
</template>
<script>
export default {
    name: 'helloVue',
    data() {
        return {
            div1: '1',
            div2: '2',
        }
    }
}
</script>

条件渲染

v-if — v-else

根据结果只渲染其中的一个div

<template>
	<div v-if="flag">true</div>
	<div v-else>false</div>
</template>
<script>
export default {
    name: 'helloVue',
    data() {
        return {
            flag: true,
        }
    }
}
</script>

v-show

<template>
	<div v-show="flag">true</div>
</template>
<script>
export default {
    name: 'helloVue',
    data() {
        return {
            flag: true,
        }
    }
}
</script>

v-show与v-if区别!!!

两者都可以条件渲染

v-if:在渲染时会直接删除v-else组件,同时v-if是惰性的,即初始渲染时不会渲染v-if,只有v-if第一次为true时才渲染,基于js,切换开销大

v-show:初始化时就被渲染,与truefalse无关,只是显示与不显示的问题,基于css <style="display:none">,初始化开销大

使用建议:频繁切换使用v-show,否则使用v-if

列表渲染

v-for

动态绑定渲染列表

节省性能,当动态修改数据时,不会重新渲染不变的数据,只会渲染变化的数据,即就地更新,该功能需要搭配:key判断哪些数据发生变化

<template>
	<ul>
        <li v-for="item in list" :key="item.id">{{item.title}}</li>
    </ul>
</template>
<script>
export default {
    name: 'helloVue',
    data() {
        return {
            list:[
                { id: 1,
                  title: "1"
                },
                { id: 2,
                  title: "2"
                },
            ]
        }
    }
}
</script>

事件处理

v-on

监听事件,在触发事件时执行jsv-on:click="method" <-----> @click="method"

<template>
	<button @click="onClick">点击</button>
	<button @click="say('hello')">hello</button>
	<button @click="say('hi')">hi</button>
	<p>{{message}}</p>
</template>
<script>
export default {
    name: 'helloVue',
    data() {
        return {
            message: 'helloMessage',
        }
    },
    methods: {
    	onClick(event) {
            // 在事件中,读取data中的属性,需要通过this.属性
            this.message = "byeMessage";
            // event是原生DOM event
            event.target.innerHTML = "点击了";
        },
       	// 同一个方法打印不同的参数 hi hello
        say(data) {
            console.log(data);
        }
    }
}
</script>

表单输入绑定

v-model

数据双向绑定,可用于<input> <textarea> <select>

v-model.lazychange事件后同步 v-model.trim过滤输入的首尾空白字符

<template>
	<input type="text" v-model="username">
	<p>{{username}}</p>
</template>
<script>
export default {
    name: 'helloVue',
    data() {
        return {
            username: "",
        }
    }
}
</script>

组件基础

单文件组件

由模板<html>、逻辑<js>、样式<css>封装成的单个文件

<template>
</template>
<script>
</script>
<style>
</style>

加载组件

<template>
	// 显示组件
    <xxxComponent></xxxComponent>
</template>
<script>
// 引入组件
import xxxComponent from './xxxComponent.vue'
export default {
    name: 'helloVue',
    // 挂载组件
    components: {
        xxxComponent,
    },
}
</script>
// scoped: 该样式只在当前组件生效
<style scoped>
</style>

Props组件交互

实现父组件向子组件传递数据

子组件

<template>
	<p>{{title}}</p>
	<ul>
        <li v-for="(item, index) in names" :key="index">{{item}}</li> 
    </ul>
</template>
<script>
export default {
    name: 'sonVue',
    props: {
        title: {
            type: String,
            default: "this is sonTitle",
        },
        names: {
            type: Array,
            default: function(){ return [] },
        },
    }
}
</script>
<style scoped>
</style>

父组件

<template>
    <sonVue :title="title"/>
</template>
<script>
import sonVue from './sonVue.vue'
export default {
    name: 'fatherVue',
    components: {
        sonVue,
    },
    data() {
        return {
            title: "this is fatherTitle"
            names: ["xiaozhang", "xiaowang", "xiaoli"]
        }
    }
}
</script>
<style scoped>
</style>

自定义事件组件交互

实现子组件向父组件传递数据

子组件

<template>
	<button @click="sendToFather">sendToFather</button>
</template>
<script>
export default {
    name: 'sonVue',
	data() {
    	return {
            message: "son--->father",
        }
    },
    methods {
		sendToFather() {
            // 参数一,字符串,随便写,有意义即可
            // 参数二,传递的数据
            this.$emit("onEvent", this.message)
        }
    }
}
</script>
<style scoped>
</style>

父组件

<template>
    <sonVue @onEvent="getSonMessage"/>
	<p>{{message}}</p>
</template>
<script>
import sonVue from './sonVue.vue'
export default {
    name: 'fatherVue',
    components: {
        sonVue,
    },
    data() {
        return {
            message: "",
        }
    },
    methods: {
        getSonMessage(data) {
            this.message = data;
        },
    },
}
</script>
<style scoped>
</style>

组件生命周期

八个生命周期函数,自动调用,不需要用户调用

创建时:beforeCreatecreated

渲染时:beforeMountmounted

mounted:组件渲染完成后再进行网络请求,然后将数据渲染到页面

更新时:beforeUpdateupdated

卸载时:beforeUnmountunmounted

beforeUnmount:卸载之前,清理掉消耗性能的处理,比如定时器

Axios网络请求

安装

npm install --save axios

引入

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

// 全局引入 main.js
const app = createApp(App);
app.config.globalProperties.$axios = axios
app.mount('#app')

// 组件中调用
this.$axios

使用

<template>
</template>
<script>
import axios from "axios"
export default {
    name: 'axiosTest',
    mounted() {
        // get
        axios.get('http://www.xxx.com').then(res => {
            console.log(res.data);
        })
        
        //post
        axios.post('http://www.xxx.com', {
            id: 1
        }).then(res => {
            console.log(res.data);
        })
    }
}
</script>
<style scoped>
</style>

Axios网络请求封装

import { createApp } from 'vue'
import axios from 'axios'

const app = createApp(App)
app.use(store).use(router).mount('#app')

// axios拦截器
axios.interceptors.request.use(
    function (config) {
        console.log('请求参数:', config);
        return config;
    }, error => {
        return Promise.reject(error);
    }
);

axios.interceptors.response.use(
    function (response) {
        console.log('返回结果:', response);
        return response;
    }, error => {
        console.log('返回错误:', error);
        const status = error.response.status;
        if (status == 401) {
            console.log("访问超时");
        }
        return new Promise((resolve, reject) => { }).catch((error) => { })
    }
);
export default axios;

路由

vue-router

管理页面之间的关系

安装

npm install --save vue-router

配置路由文件 router/index.js

import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    component: () => import('../views/indexView.vue'),
    children: [
      {
        path: 'welcome',
        component: () => import('../views/main/welcomeView.vue')
      },
    ]
  },
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router;

引入路由 main.js

import router from './router'
const app = createApp(App)
app.use(router).mount('#app')

指定路由显示入口

<template>
  <router-view />
</template>
<script>
</script>
<style>
</style>

携带参数路由

{
    path: '/index/:name',
    component: () => import('../views/indexView.vue'),
}

<template>
	<router-link to="/index/hello"></router-link>
</template>

<p>{{ $router.params.name }}</p>
    

Vuex

管理组件之间的状态

安装

npm install --save vuex

引入vuex main.js

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

state

配置vuex文件 store/index.js

import { createStore } from "vuex"

export default createStore({
    state: {
        counter: 0
    }
})

读取数据

//方案一
<template>
	<p>{{$store.state.counter}}</p>
</template>
// 方案二
<template>
	<p>{{counter}}</p>
</template>
<script>
import { mapState } from "vuex"
export default {
    name: 'storeTest',
    computed: { ...mapState(["counter"]) }
}
</script>
<style scoped>
</style>

getter

import { createStore } from "vuex"

export default createStore({
    // state 用于存储数据
    state: {
 		counter: 1
    },
    //getter 用于过滤数据
    getters: {
        getCount(state) { return state.counter > 0 ? state.counter: "error" }
    }
})

读取过滤后的数据

// 方案一
<template>
	// 读取过滤后的数据
	<p>{{$store.getters.getCount}}</p>
</template>

// 方案二
<template>
	<p>{{getCount}}</p>
</template>
<script>
import { mapGetters } from "vuex"
export default {
    name: 'storeTest',
    computed: { ...mapGetters(["getCount"]) }
}
</script>
<style scoped>
</style>

mutation

用于修改数据,只能同步操作

import { createStore } from "vuex"

export default createStore({
    state: {
 		counter: 1
    },
    getters: {
        getCount(state) { return state.counter > 0 ? state.counter: "error" }
    },
    mutations: {
    	setCount(state, num) { state.counter += num }
	}
})

修改数据

<template>
	<p>{{getCount}}</p>
	<button @click="onClick">click</button>
</template>
// 方案一
<script>
import { mapGetters } from "vuex"
export default {
    name: 'storeTest',
    computed: { ...mapGetters(["getCount"]) },
    methods: {
        onClick() {
            // 固定调用方式
            this.$store.commit("setCount", 2)
        }
    }
}
</script>
// 方案二
<script>
import { mapGetters, mapMutations } from "vuex"
export default {
    name: 'storeTest',
    computed: { ...mapGetters(["getCount"]) },
    methods: {
        ...mapMutations(["setCount"]),
        onClick() { this.setCount(2) }
    }
}
</script>
<style scoped>
</style>

action

异步操作时才需要action,action提交的是mutation,不是直接变更状态

import { createStore } from "vuex"
import axios from "axios"
export default createStore({
    state: {
 		counter: 1
    },
    getters: {
        getCount(state) { return state.counter > 0 ? state.counter: "error" }
    },
    mutations: {
        setCount(state, num) { state.counter += num }
	},
    actions: {
    	asyncSetCount({ commit }) {
            // 异步操作,获取到后端数据,然后调用mutation修改数据
    		axios.get('http://www.xxx.com').then(res => {
                commit("setCount", res.data)
            })
	    }
	}
})

修改数据

<template>
	<p>{{getCount}}</p>
	<button @click="onClick">click</button>
	<button @click="onAsyncClick">asyncClick</button>
</template>
// 方案一
<script>
import { mapGetters } from "vuex"
export default {
    name: 'storeTest',
    computed: {
      ...mapGetters(["getCount"])  
    },
    methods: {
        onClick() {
            // 固定调用方式
            this.$store.commit("setCount", 2);
        },
        onAsyncClick() {
            this.store.dispatch("asyncSetCount");
        }
    }
}
</script>
// 方案二
<script>
import { mapGetters, mapMutations,mapActions } from "vuex"
export default {
    name: 'storeTest',
    computed: {
      ...mapGetters(["getCount"])  
    },
    methods: {
        ...mapMutations(["setCount"]),
        ...mapActions(["asyncSetCount"]),
        onClick() {
            // 固定调用方式
            this.setCount(2)
        },
        onAsyncClick() {
            this.asyncSetCount();
        }
        
    }
}
</script>
<style scoped>
</style>

vue3新特性

组合API、更优秀的Ts支持

ref&reactive

<template>
	<p>{{message}}</p>
	<ul>
    	<li v-for="(item, index) in names.list" :key="index">{{item}}</li>
    </ul>
	<button @click="onClick">click</button>
</template>
<script>
import { ref, reactive } from "vue" 
export default {
    name: "hello ref&reactive",
    //组合式API
    setup() {
        // ref
        const message = ref("hello ref&reactive")
        // reactive
        const names = reactive({
            list: ["xiaozhang", "xiaowang", "xiaoli"]
        })
        function onClick() {
            message.value="hello click";
            console.log("click");
        }
        return {
            message,
            names,
            onClick
        }
    }
}
</script>

props&context

子组件

<template>
	<p>{{title}}</p>
</template>
<script>
import { ref, reactive } from "vue" 
export default {
    name: "hello ref&reactive",
    props: {
    	title:String
    }
    // setup中不能使用this, 而是被context代替
    // this.title也被淘汰,直接使用title
    setup(props, ctx) {
        console.log(ctx);
        const title =  props.title;
        return {
            title,
        }
    }
}
</script>

父组件

<template>
    <sonVue title="FatherTitle"/>
</template>
<script>
import sonVue from './sonVue.vue'
export default {
    name: 'fatherVue',
    components: {
        sonVue,
    },
}
</script>
<style scoped>
</style>

生命周期函数

在这里插入图片描述

provide&inject

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值