官方文档 https://cn.vuejs.org/
demo地址
https://gitee.com/galen.zhang/vue3-demo/tree/master/vue3-base-api
Vue3常用插件
Volar、Vue VSCode Snippets、Auto Close Tag、Vue Peek、Vite
测试模板文件 template.html
Vue模板
Vue实例
v-model
实现数据和表单元素绑定
v-model
的修饰符:tirm
、number
前面{{msg}}后面
+={{a+b}}
v-on
绑定事件,可以简写为 @
修饰符 https://cn.vuejs.org/guide/essentials/event-handling.html#key-modifiers
v-bind
绑定属性,可以简写成:
#script
// 对象表示样式的时候,属性名表示样式名,属性值为bool值(true表示生效,false表示无效)
classP3: {
a: true,
b: false,
c: true,
},
watch
监听一个数据的改变,数据改变之后执行一个操作
computed
计算属性,当依赖的数据改变之后会重新计算一个结果
计算属性具有缓存功能
计算属性和方法调用的区别:
// 模拟购物中全选、取消选择,计算总价
-
总价:{{sumPrice}}
// script
data() {
return {
carts: [
{
id: 1,
name: "外套",
chk: false,
amount: 2,
price: 100,
},
{
id: 2,
name: "裙子",
chk: true,
amount: 1,
price: 50,
},
{
id: 3,
name: "鞋子",
chk: false,
amount: 3,
price: 200,
},
],
};
},
computed: {
// 直接返回一个结果,相当于只设置了get
double() {
console.log("计算属性执行了");
return this.num * 2;
},
// 另一种写法
// set表示主动设置值
// get表示被动取值
chkAll: {
set(v) {
// console.log(v);
this.carts.forEach((item) => (item.chk = v));
},
get() {
return this.carts.every((item) => item.chk);
},
},
sumPrice() {
return this.carts
.filter((item) => item.chk) // 获取选中的
.reduce((pre, cur) => pre + cur.price * cur.amount, 0); // 求和
},
},
refs
获取dom元素
nextTick
Vue中dom更新是异步的,数据改变后无法直接获取dom中的最新值。使用这个api可以获取到
当前的num为:{{num}}
// script
data() {
return {
num: 1
};
},
methods: {
clickHandle() {
this.num++;
// console.log(this.$refs.txt.innerText);
// $nextTick 是一个内置的全局api,可以在其回调函数中获取dom的最新值
this.$nextTick(() => {
console.log(this.$refs.txt.innerText);
});
},
}
自定义标签
组件传参
Vue 组件
Vue实例
8个常见的生命周期钩子函数
下面2个需要配合keep-alive使用。keep-alive可以对组件做缓存
嵌套组件的生命周期钩子函数
component
动态组件,通过is属性控制当前显示哪一个组件
2种创建项目的方式
npm init vite@latest
npm create vue@latest
npm init vite@latest
vue-demo
#文档
https://cn.vuejs.org/guide/quick-start.html#creating-a-vue-application
cd vue-demo
npm install
npm run dev
script setup
语法方式
Vue3
{{ txt }}
npm i vue-router
定义路由文件 router/index.js
import { createRouter, createWebHashHistory } from "vue-router";
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: "/",
name: "Home",
component: () => import("../views/Home.vue"),
},
{
path: "/user",
name: "User",
component: () => import("../views/User.vue"),
},
],
});
//路由前置守卫
router.beforeEach((to, from, next) => {
console.log("beforeEach");
next();
});
export default router;
在 main.js
中引入路由
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
测试一下,在 App.vue
中加入路由链接
【首页】
【列表】
【我的】
demo地址
https://gitee.com/galen.zhang/vue3-demo/tree/master/vue-demo
处理组件复用不会再次初始化数据
http://localhost:5173/#/list // 查询所有数据
http://localhost:5173/#/list?tid=1
url路由改变了,但组件复用不会重新初始化
列表
【{{ item.name }}】
computed
计算属性
如果只需要计算出一个值,参数为一个函数,返回计算的结果
如果需要主动设置值+被动改变,传入一个对象,里面包含set/get函数
-
价格:{{ item.product.price }}
数量:{{ item.amount }}
总价:{{ sumPrice }}
#https://vant-contrib.gitee.io/vant/#/zh-CN
npm i vant
在 main.js
中引入样式
import { createApp } from 'vue'
import 'vant/lib/index.css'; // 引入vant的样式库
import './style.css'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
在页面中引入需要使用的vant组件
在 App.vue
中增加Tabbar组件
首页
热卖
购物车
我的
调整整个页面布局 style.css
html,body,#app {
height: 100%;
}
#app {
display: flex;
flex-direction: column;
}
1
2
3
4
{{ proudct.name }}
是否需要隐藏底部Tabber
meta
{
path: "/detail",
name: "Detail",
component: () => import("../views/Detail.vue"),
meta: {
needHideTabber: true, // 需要隐藏底部Tabber
},
},
App.vue
中监听路由的变化
首页
热卖
购物车
我的
npm i axios
// 进度条
npm i nprogress
#测试后台接口数据
#https://gitee.com/galen.zhang/vue3-demo/tree/master/honey-home-main/honey-home-server
cd honey-home-server
npm i # 安装依赖项
node app.js # 启动项目
http://localhost:1337
http://localhost:1337/api/products
http://localhost:1337/manager
#管理页面
封装axios使用 utils/request.js
import axios from "axios";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
export const serverUrl = "http://localhost:1337";
const service = axios.create({
baseURL: serverUrl,
timeout: 5000,
});
// Add a request interceptor 全局请求拦截
service.interceptors.request.use(
function (config) {
// Do something before request is sent
NProgress.start(); // 启动进度条
// 此处还可以设置token
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
}
);
// Add a response interceptor 全局相应拦截
service.interceptors.response.use(
function (response) {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
NProgress.done();
// 如果是固定的数据返回模式,此处可以做继续完整的封装
return response.data;
},
function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
NProgress.done();
// 此处需要对返回的状态码或者异常信息作统一处理
return Promise.reject(error);
}
);
export const get = (url, params) => {
return service.get(url, {
params,
});
};
export const post = (url, data) => service.post(url, data);
export const put = (url, data) => service.put(url, data);
export const del = (url, data) => service.delete(url);
使用样例 api/categories.js
import { get } from '../utils/request';
/**
* 获取商品分类
* @returns
*/
export const loadCategoriesAPI = () => get('/api/v1/product_categories');
创建文件 hooks/use-categories.js
import { ref } from "vue";
import { loadCategoriesAPI } from "../api/categories";
export const useCategories = () => {
const categories = ref([]);
loadCategoriesAPI().then((res) => (categories.value = res.data));
return {
categories,
};
};
使用方式