目录
(一) 创建项目#
(1) 创建vue2项目#
(二)vue2不需要vite,但需要禁用Eslint
(三) 添加vant-ui
vue2#
(四)vue2,3都可以通用less,scss
(六) vue路由配置(背诵)#
01 安装vue-cli脚手架
npm install -g @vue/cli
02 查看vue脚手架版本
vue --version // 出现版本号表示成功
03 创建一个新项目
vue create hello-world // 创建项目
运行项目
cd hello-world // 进入项目文件夹
npm run serve // 运行项目
// 根目录新增vue.config.js
module.exports = {
lintOnSave: false
}
如果vue组件提示红色错误,如下图
解决办法: 文件 -> 首选项 -> 设置 然后输入eslint -> 选择Vetur -> 把√取消即可
vant2地址: Vant 2 - Mobile UI Components built on Vue
安装依赖
使用
import Vue from 'vue'
import App from './App.vue'
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
(1)一个简单路由配置#
npm i vue-router@3
安装路由插件import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
// 路由数组
const routes = [
{
path: '/product',
component: ()=>import('@/views/product/index.vue')
},
{
path: '/cart',
component: ()=>import('@/views/cart/index.vue')
},
]
const router = new Router({
routes
})
export default router;
// main.js 代码
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
Vue.config.productionTip = false
new Vue({
// 把router挂载到vue实例
router,
render: h => h(App),
}).$mount('#app')
(2) router-view#
(3) 路由跳转#
// 方式一
cart
// 方式二
this.$router.push('/cart');
(4) 子路由配置#
使用子路由进行模块路由配置,结构比较分明 比如我们的网站有商品模块,有列表页面和详情页面, 路由如下 /product 商品模块总路由 /prodcut/list 子路由 /product/detail 子路由
{
path: '/product',
component: () => import('@/views/product/index'),
children: [
{
path: 'list',
component: ()=>import('@/views/product/children/list')
},
{
path: 'detail',
component: ()=>import('@/views/product/children/detail')
}
]
}
(5) active-class#
active-class是vue-router模块的router-link组件中的属性,用来做选中样式的切换;
首页
product
cart
my
order
(6) history模式#
vue2配置方式
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面
使用history需要后端支持, vue-cli创建的devServer可以支持
const router = new VueRouter({
mode: 'history', // 默认hash
routes
})
(7) redirect重定向#
当访问 '/', 我们使用redirect使它默认跳到 '/product'
{
path: '/',
redirect: '/product'
},
(8) 404配置#
假如用户访问了一个没有的路由, 我们让它跳转到404页面
{
path: '*',
component:()=>import('@/components/NotFound')
}
知识点(背诵):
父组件给子组件绑定属性, 属性的值是需要传递的信息
简单概括就是: 父组件通过属性给子组件传数据
子组件通过props接收父组件的信息
// demo.vue 充当父组件
父组件
// AAA.vue 充当子组件
子组件
{{msg1}}
{{msg2}}
// 例子1: 一个简单的例子
// demo.vue
父组件
// 子组件
子组件
import axios from "axios";
import Vue from "vue";
import { Toast } from "vant";
Vue.use(Toast);
const service = axios.create({
baseURL: "http://huruqing.cn:3003",
timeout: 50000, // 请求超时时间(因为需要调试后台,所以设置得比较大)
});
// request 对请求进行拦截
service.interceptors.request.use(
(config) => {
// 开启loading
Toast.loading({
message: "加载中...",
forbidClick: true,
loadingType: "spinner",
});
// 请求头添加token
config.headers["token"] =
"gg12j3h4ghj2g134kj1g234gh12jh34k12h34g12kjh34kh1g";
return config;
},
(error) => {
Promise.reject(error);
}
);
// response 响应拦截器
service.interceptors.response.use(
(response) => {
Toast.clear();
const res = response.data;
if (res.code == 666) {
return res;
} else {
// 成功连接到后台, 但是没有返回正确的数据
Toast.fail(res.msg);
}
},
(error) => {
Toast.clear();
// 跟后台连接失败
Toast.fail("网络异常,请稍后再试");
}
);
export default service;
知识点:
通过params传参, 使用$route.params接收参数
动态路由传参, 使用$route.params接收参数
通过query传参, $route.query接收参数
注意: router和route不是一回事
// 带查询参数,query传参会把参数拼接到地址栏,变成 /register?plan=aaa, 使用了path,参数不能通过params传递
this.$router.push('/goods?name=张三');
this.$router.push({
path: '/goods',
query: { plan: 'aaa' }
})
// 获取参数
this.$route.query;
// 1.配置路由的时候添加name
{
path: "detail",
name: 'product-detail',
component: () => import("@/views/order/children/detail"),
},
// 2.跳转
this.$router.push({
// 要跳转到的路由名称
name: 'product-detail',
params: { productId: '123' }
})
// 3.接收参数
this.$route.params.productId
// 1.配置路由
{
path: "detail/:productId",
component: () => import("@/views/product/children/detail.vue"),
},
// 2. 跳转
this.$router.push('/product/detai/22222')
传参
// 3.接收参数
created() {
let params = this.$route.params;
console.log('params',params);
},
元素作为承载分发内容的出口 一个内存插槽, 当内存插上之后,插槽就可以接收来自内存的信息, slot取名插槽含义也贴切, 在子组件配置插槽slot, 当父组件"插"信息进来的时候, 插槽slot就能接收到这个信息. slot插槽大大的扩展子组件的功能。
1. vant有赞ui库中slot的例子#
2. 普通插槽#
// 父组件demo.vue代码
父组件
// 子组件Son.vue
3. 具名插槽#
// father.vue代码
这是父组件
这是头部
接收父组件带 slot="footer" 的内容
接收不带slot="xxx" 的内容
// Child.vue代码
这是子组件
自定义组件
// demo.vue
// Nav-Bar.vue
作用: 格式化数据
// 组件内的过滤器
{{num | f}}
// 全局过滤器
Vue.filter('fMoney', (money)=> {
let num = money/100;
return num.toFixed(2);
})
new Vue({})
// 定义好全局过滤器后, 组件内可以直接使用
{{num | fMoney}}
vuex是什么: ** vuex是一个专为 Vue.js 应用程序开发的状态管理模式**。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
术语解读:
给项目添加vuex
state 定义状态
getters 派生状态
mutation 修改状态(同步)
action 修改状态(异步)
module 模块化
vuex持久化
项目实践
注: 前第2-6个是vuex的核心概念, 第7和第8是项目的应用
安装依赖
npm i vuex@3
创建并导出store
// src/store/index.js
// 创建并导出store
import Vuex from 'vuex';
import Vue from 'vue';
Vue.use(Vuex);
const store = new Vuex.Store({
})
export default store;
挂载store
// src/main.js
import store from './store/index';
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
// 定义状态 src/store/index.js
const store = Vuex.Store({
state: {
username: "张三",
},
});
// 获取状态方法(1) demo.vue
{{username}}
// 获取状态方法(2) demo.vue
{{username}}
{{age}}
mutatiaon改变, 定义一个mutation, 本质上就是定义一个用来修改state的函数
// 创建并导出store
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex);
const store = new Vuex.Store({
// 定义状态
state: {
username: "张三",
age: 100
},
mutations: {
// 定义修改名字的mutation
set_username(state,payload) {
state.username = payload;
},
// 定义修改age的mution
set_age(state,payload) {
state.age = payload;
}
}
});
export default store;
// 绑定事件来触发修改状态
{{username}}
{{age}}
跟computed差不多意思, computed是由一个或多个属性计算出另外一个属性, 你也可以说派生出另外一个属性
getters: 由一个或多个状态计算出一个新的状态
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex);
const store = new Vuex.Store({
// 定义状态
state: {
cartId: 452520199508150320,
},
getters: {
// 由cartId派生出生日
birthdate(state) {
// 字符串才能使用slice方法
let cartId = state.cartId + '';
let Y = cartId.slice(6, 10);
let M = cartId.slice(10, 12);
let D = cartId.slice(12, 14);
return `${Y}-${M}-${D}`;
},
},
});
export default store;
定义action 注意, 修改状态必须使用mutation, mutation必须是同步函数
一个action的全流程: 用户点击按钮 => 派发响应的action => action去commit响应的mutation => mutation 去修改state => state改变了, 界面跟着发生改变
// 定义action
// 创建并导出store
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex);
import $axios from '@/api/request'
const store = new Vuex.Store({
// 定义状态
state: {
smsCode: "请先获取验证码",
},
mutations: {
set_smsCode(state,payload) {
state.smsCode = payload;
}
},
actions: {
['SMSCODE'](store,phone) {
$axios.post('/user/getSmsCode',{phone}).then(res=> {
store.commit('set_smsCode',res.smsCode);
})
},
},
});
export default store;
// 使用dispatch方法来派发action
{{smsCode}}
// 定义cart模块的store src/store/modules/cart.js
const cartStore = {
state: {
cartNum: 0,
},
getters: {},
mutations: {
set_cartNum(state,payload) {
state.cartNum = payload;
}
},
actions: {}
}
export default cartStore;
// 合并store
// 创建并导出store
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex);
import cart from "./modules/cart";
const store = new Vuex.Store({
// 定义状态
state: {},
modules: { cart },
mutations: {},
actions: {},
});
export default store;
// 使用 demo.vue
{{cartNum}}
安装插件 vuex-persistedstate
配置插件
import createPersistedState from "vuex-persistedstate";
// 创建仓库 - 就是Vuex.Store() 的实例对象
const store = new Vuex.Store({
plugins: [createPersistedState({
storage: window.sessionStorage, // 使用的缓存, 默认是localStorage
})],
})