第一章、走进Vue3.0
2-1、下载Vue3.0的单文件核心库
vue3.0 源码下载地址: https://unpkg.com/[email protected]/dist/vue.global.js
sp1、github搜索vue, 到vuejs首页:其中"vue"项目是vue2.0版本, 选择"vue-next"项目(vue3.0版本)进入
sp2、选择"Branch:master"-->"Tags"查看最新版本, 通过UNPKG网站来下载我们需要的单文件, 比如: https://unpkg.com/[email protected]/dist/vue.global.js
sp3、打开地址, 复制文字保存为.js文件.
2-2、简单指令v-text、v-html、v-bind
2-9、v-on指令监听事件
2-10、条件渲染之v-if和v-show的选择
2-11、多项条件渲染
hello, 10月
2-12、v-for列表渲染及扩展用法及注意事项
- 长秀
- 长歌
- 藏剑
- {{item}}{{index}}
- {{item}}{{index}}
- {{item}}{{index}}
- {{value}}{{key}}{{index}}
第二章、Vue3.0中的响应式对象
1-1、双向数据绑定
1-3、双向数据绑定与响应式对象
proxy 对对象进行代理一样的拦截, 去操作某一对象下某一个属性时, 无论读取或写入, 都会给你一次机会写写自己的业务逻辑. 它提供了两个方法set(设置数据做监听)、get(获取数据做监听).
响应式对象的使用范畴比双向数据绑定更广
1-4、Vue3.0响应式对象使用场景
{{number}}
2-1、Vue3.0中的watch函数
{{firstName+lastName}}
2-2、Vue3.0中的watch函数--基本使用范例
{{fullName}}
2-3、Vue3.0中的watch函数--高级用法监听reactive对象
{{fullName}}
2-4、Vue3.0中的watch函数--高级用法监听reactive对象下单个属性
{{name.fullName}}
3-1、watch小结与引入computed计算属性
建议通常使用watch监听单个属性, 或者监听reactive某一个属性变化. 最好不要监听一整个对象的变化.
computed 计算属性 : 比watch更适合计算一个属性, 并且绑定
3-2、computed函数的基本用法
{{fullName}}
3-3、watch、computed、普通js函数的使用场景和区别
{{getFullName()}}
3-4、computed的set和get方法
{{fullName}}
第三章、 Vue3.0 中的组件
1-1、 Vue3.0中的组件如何编写?
1-2、Vue4.xCli创建Vue3项目或者使用Vite创建Vue3项目
/*用脚手架快速创建初始实例应用程序的两种方法: cli创建 或 vite创建
vue的cli创建应用程序:
sp1.终端命令
安装npm, 验证 $ npm -v
安装vue的脚手架工具-cli, $ sudo npm i -g @vue/cli
sp2.创建vue的应用程序
$ cd 存放项目的文件夹目录下
$ vue create 项目名
可以自定义安装, 通过空格选中和取消选中
sp3.项目升级到vue3.0
$ vue add vue-next
vite是vue3提供的小工具, 旨在替换webpack
sp1. 创建一个名为old-time-vite的项目
回退到项目根目录 $ cd ..
$ npm init vite-app old-time-vite
sp2.运行项目
$ cd old-time-vite/
$ npm install
$ npm run dev
*/
1-3、一切皆组件
组件化编程: 一切都是组件
1-4、VueCli应用程序目录结构解析
cli最重要的两个功能是帮助我们构建和打包; vite也可以不过刚出来,它里面没有webpack,它的模式是用浏览器的标准模块加载的方式, 和cli的webpack不太一样,它的优点vite要求它的库所有版本都是vue3.0版本的.但cli比较成熟, 比较推荐cli来构建项目.
-- src //源码文件
-- components //组件目录
-- App.vue // 应用入口文件: 严格意义来讲就是一个组件
组件模版(骨架)
-- main.js // JavaScript的入口文件: vue启动的时候它要去执行的一个文件,类似小程序的app.js
-- .eslintrc.js // 是一个语法编码检测的一个文件
-- babel.config.js // 浏览器兼容方面的配置
-- package.json
-- package-lock.json // 记录我们npm包的一个文件
项目部署 $ npm run build #打包后,项目自动生成一个dist目录.dis目录就是一个生成编译之后的所有文件.那dis文件去部署就行了
1-5、Vue里自定义组件的定义与引入
// 创建HelloWorld.vue组件, 在HelloWorld.vue中:
{{ msg }}
// 引入组件, 在App.vue中:
2-1、导入resetcss并显示一张图片
//通常我们做H5开发的时候都要引入一个重置浏览器默认样式的一个css的文件, 主要作用是把默认属性值全部归零.
sp1.将重置浏览器样式文件reset.css放到assets文件夹下的style文件中
sp2.在main.js文件中引入reset.css文件:
import './assets/style/reset.css' //要用单引号
2-2、我的第一个vue3.0自定义组件
sp1. 在components文件中, 新建自定义组件swiper.vue(文件名尽可能命名为小写), 在swiper.vue中:
//scoped表示在style里写的样式,仅仅局限于当前组件的内部,不会影响其他组件
sp2.在App.vue中, 引入swiper.vue组件:
2-5、使用require加载图片
如何给vue定义一个属性, 然后让调用方将属性的值传入组件内部来使用?
在swiper.vue中:
在App.vue中:
2-6、Vue3 setup函数在组件中的使用
2-7、props属性传值时需要注意使用v-bind指令确定类型
在App.vue中:
在swiper.vue中:
3-1、vue的单向数据流特性
值类型和引用类型
如果是一个number类型的数据A, 父组件把数据A传到子组件后, A的值是不能改的, 因为被vue设置成了只读类型.
什么是vue的单向数据流?
vue要求值可以在父组件里面被更新,如果在子组件里更新值, 默认情况下是不允许的.vue这么做是因为: 如果一个值A传到子组件,子组件又将值传入子子组件, A会贯穿多个组件,那么如果中间某个组件改变了A的值,其他组件也会受影响,会造成很多调试问题
在swiper.vue中:
3-2、父组件改变导致子组件的变化
在父组件改变num的值, 使用响应对象
在App.vue中:
在swiper.vue中:
{{num}}
3-3、引用类型的修改导致父组件异常
证明一句话, 不能反向的通过子组件改变父组件
在App.vue中:
在swiper.vue中:
第四章 vue-router与vuex
1-1 自定义组件监听原生事件
子组件如何把数据传递到父组件:
最常用的方法: 子组件通过自定义事件传递数据到父组件中
1-2 自定义组件的自定义事件与传参 (最常用)
在swiper.vue中:
{{num}}
在App.vue中:
1-4 初识Vue3.0的Router
可参照链接操作: https://segmentfault.com/a/1190000022684511
终端操作:
$ vue create vue-new #创建项目
$ 选择 "Manually select features" #手动选择
$ 空格勾选 "Babel"、"Router"、"Vuex"、"Linter/Formatter"、"CSS Pre-processors"(#CSS预处理器,可以不勾选)
$ n (不使用history router)
$ 选择"Sass/SCSS (with node-sass)" #如果之前勾选了CSS预处理器,会来到这里
1-5 自己定义一个detail页面路由
目标任务: 当我们在子组件swiper.vue中,点击后触发onImgClick(),跳转detail.vue页面
在 src/views/ 目录下,新建detail.vue页面:
商品详情页面
在src/router/index.js文件中, 定义路由:
import Home from '../views/Home.vue'
import Detail from '../views/detail.vue' // sp2.导入Detail
const routes = [
{//方式一: 使用import的方式导入(推荐)
path: '/',
name: 'Home',
component: Home
},
{//方式二: 使用了webpack的方式进行导入的
path: '/about',
name: 'About',
component: () =>import('../views/About.vue')
},
{//sp3.添加Detail路由
path: '/detail',
name: 'Detail',
component: Detail
}
]
2-1 router-view与router-link
在App.vue中:
Detail
2-2 vue-router编程思想
本质上都是组件, 只是做了规范约定如下:
通常views文件夹下放的组件是要关联router的, 但是components文件夹下放的组件是不会关联rooter的.
components: 里面的组件主要是为了复用, 通常会被多个views复用
views: 里面的组件主要为了被当做页面上的显示区域, 通常是不会复用的
2-3 vue-router编程思想--入口组件的规范
页面的变化用路由切换, 尽量不用条件渲染.
任务目标: 精简App.vue, 把之前的swiper组件迁移到新页面home.vue中,方便后面路由跳转.
在App.vue中:
在 views/ 下创建home.vue, 在home.vue中:
Detail
2-4 vue-router编程思想--router-view监听事件
任务目标: 通过冒泡将事件一步步传递到App.vue, 执行路由展示
在swiper.vue中:
{{num}}
在home.vue中:
在App.vue中:
2-5 vue-router编程思想--组件的切换优先考虑路由而不是条件渲染
任务目标: 实现简单的页面跳转
/*在vue中不管是组件还是页面都推荐用路由的方式进行切换,而不是条件渲染*/
2-6 默认情况下不能跨父组件通信
在Vue中默认情况下不能跨父组件进行通信
3-1 嵌套路由
如果说一个组件是另一个组件的子组件, 那么它通常要显示在它的父组件view中. 比如SubDetail被配置成了Detail的子组件, 那么SubDetail要想被显示出来需要在Detail中的view里写上 ,那么就会把SubDetail默认显示出来了.
在index.js中:
import { createRouter, createWebHashHistory } from 'vue-router'
import SubDetail from '../views/sub-detail.vue'
const routes = [
{
path: '/detail',
name: 'Detail',
component: Detail,
//嵌套子路由
children:[
{
path:'sub',//路径先当于/detail/sub
name: 'SubDetail',
component: SubDetail
}
]
},
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
在detail.vue中:
商品详情页面
3-3 多页面跳转change-view
任务目标: 通过App.vue动态切换任意页面
在App.vue中:
在home.vue中:
3-4 Vue3中如何获取路由参数
目标任务: 传递并获取路由参数.
在index.js中:
const routes = [
{
path: '/detail/:id',//sp1.一定要传递固定参数id
name: 'Detail',
component: Detail
},
]
在home.vue中:
在detail.vue中:
3-5 Vue3中的路由名称与统一跳转页面逻辑
任务目标: 通过路由name传参
在index.js中:
const routes = [
{
path: '/detail/:id',//一定要传递固定参数id
name: 'Detail',
component: Detail
},
{
path:'/detail/sub',
name: 'SubDetail',
component: SubDetail
},
]
在home.vue中:
在App.vue中:
4-1 为什么需要Vuex全局状态管理
组件都有一定的独立性, 需要事件传参. 另一个传参的方法Vuex,是一种可以存储全局变量的机制.
Vuex全局变量与html的全局变量的区别:
1.Vuex全局变量天生是响应式的; 2.Vue对全局状态的管理很多的操作是有记录性质的,不能直接修改, 要通过方法的方式去操作它(因为Vue需要追踪记录这些变化修改).
4-2 定义Vuex的全局变量
最终目标任务: 通过Vuex解决路由跳转的问题, 比如home.vue跳转detail.vue页面.
目标任务: 通过Vuex定义与获取全局变量
在src/store/index.js中:
export default createStore({
state: {//sp1.定义全局变量
url:'SubDetail'
},
mutations: {
},
actions: {
},
modules: {
}
})
在home.vue中:
4-3 Vuex改变全局状态变量并传参的3种方式
最终目标任务: 通过Vuex解决路由跳转的问题, 比如home.vue跳转detail.vue页面.
目标任务: 通过Vuex调用方法修改全局变量的值
在src/store/index.js中:
export default createStore({
// 定义全局变量
state: {
url:''
},
// 定义函数
mutations: {
// 通过方法的方式来改变全局变量的值
// 对应传参方式一、三:
// state就是上面的state,vue自动传入,不用我们传.
// url要改变的全局变量的值,需要我们传入
changeView(state, url){
state.url = url
}
// 对应传参方式二:
// changeView(state, payload){
// state.url = payload.url
// }
},
actions: {
},
modules: {
}
})
在home.vue中:
4-4 计算属性和监听器在Vuex状态改变时的应用
目标任务: 通过Vuex解决路由跳转的问题, 比如home.vue跳转detail.vue页面.
// 之前是通过多个事件函数回调传递到App.vue触发路由跳转事件, 现在去除了事件回调传递, 留下一个响应对象(Vuex全局变量),就在App.vue通过watch监听全局变量(响应式对象)的变化来触发路由跳转事件.
在App.vue中:
{{store.state.url}}
{{changedUrl}}
4-5 利用全局状态管理变量进行路由切换
目标任务: 全局状态管理的总结
利用全局状态管理变量进行路由切换逻辑:
在跳转路由的时候,在跳转的地方,调用 store.commit('changeView',{url: 'SubDetail'}) 方法改变url, 然后在App.vue中进行监听跳转路由操作.
什么时候需要用计算属性和watch?
如果只是想显示全局变量的值, 那么只需要计算属性就可以了;
如果要做监听这个值的改变, 并且做路由跳转等操作,就要用watch.
精简利用全局状态管理变量进行路由切换代码:
在src/store/index.js中:
export default createStore({
state: {
routerParams:{} //定义对象变量
},
mutations: {
changeView(state, payload){
state.routerParams = payload.routerParams
}
},
actions: {
},
modules: {
}
})
home.vue跳转detail.vue逻辑,在home.vue中:
在App.vue中:
同理detail.vue跳转sub-detail.vue逻辑, 在detail.vue中:
第五章 动态组件与Vuex全局状态管理
1-1 动态组件(1)总结Vue中几种切换视图组件的方案
目标任务:
1.动态组件
2.如何使用keep alive保存组件状态? keep alive是Vue内置的标签, 只需要使用keep alive包裹上动态组件就可以记录保存组件状态了
关于组件和视图的切换:
①利用路由router-view方式进行切换,用于切换大的模块视图 ②利用条件渲染(v-if)进行切换, 用于小幅度的切换 ③显示或隐藏 ④动态组件, 用于小幅度的显示或隐藏
1-2 动态组件(2)初识动态组件
什么是动态组件?动态组件就是多个组件根据条件只显示一个组件.
在home.vue中:
1-3 使用keep-alive缓存组件状态
在home.vue中:
第六章 CMS电商管理系统前端搭建
1-1 实战LinCMSVue介绍
组件库 + CMS框架
LinCMSVue -> 3.0 机制 ✅
ElementUI -> 3.0
Antd Vue
1-2 实战的准备工作
sparrow: 四阶段Lin CMS Vue源码
在 https://github.com/TaleLin/lin-cms-vue 下载0.1.0-sleeve版本到本地
1-3 下载LinCMSVue并前后端运行联调
$ cd ~/apps/c-sleeve/lin-cms-vue-0.1.0-sleeve
$ npm install
$ npm run serve #启动项目
# 前端服务器启动完毕了, 前端服务器用来下载一些vue的文件.下面启动的就是前端服务器的地址.前端服务器是由node.js启动的,所以需要node.js环境.
App running at:
- Local: http://localhost:8080/
- Network: http://192.168.0.103:8080/
1-4 权限、角色与分组的关系
# CMS最重要的是权限.
# 用户、分组、权限的关系:
用户不能直接拥有权限, 用户属于某一个分组, 分组有多个权限.
分配权限不是用户分配权限, 是分组分配权限.
1-5 字段级别的细粒度权限探讨
# 权限的实质: API
放到springboot里就是Controller.
1个权限 = 1个Controller = 1个API
# 权限粒度问题: 更多的时候指查询
比如用户A可以看到Banner的名称,但不能看到Banner的描述, 用户B不能看到Banner的名称,但可以看到Banner的描述.
方案一: 可能要写多个Controller,即权限和Controller挂钩
①权限--不返回描述 A
②权限--不返回名称 B
方案二: 权限不和Controller挂钩, 而是和数据库字段挂钩, 这样操作复杂度很高;
也可以选择使用动态SQL, 根据拥有的权限动态的拼接SQL查询语句:
select name ... from banner A
select description ... from banner B
但动态SQL只适合单表查询, 很多时候数据来自多个表, 所以很多时候SQL用join, 这样操作就复杂了
方案三: 在vo层做一个权限拦截层, vo这一层它的数据是来源多张表的,它和数据库的单表是没关系的. vo是视图, 它的作用是综合多个表的数据把他们简化成一个vo对象.
比如对某一个order来说,数据可能来自多个表,那么多个表的数据会汇总成一个order的vo对象,在这里做权限的过滤. 不会在数据库这层做权限的拼接.