013.列表渲染
- 在Vue中进行删除数组的操作的时候,会在进行的过程是
首先是在原来的数组中创建虚拟DOM,然后数据经过虚拟DOM后才会被创建出来,而如果进行删除或者添加操作的时候,就会生成新的虚拟DOM,然后通过与之前的虚拟DOM进行对比,发现不同的地方,通过补丁进行操作,最后更新真是的DOM。
需要虚拟DOM是因为创建真实的DOM属性比较多,创建比较耗费资源,所有才会有虚拟DOM来进行优化过程。
67.单文件组件-1
// ES6 导出规范
// 向外导出: export default {} 【默认导出】
// 对应的导入方式: import 名称 from ‘模块路径’ 【默认导入】
scss书写方式
vue的文件夹的名字都是小写,但是vue文件的首字母大写,这是一个建议,不是规定
68.在子组件写样式会被父组件覆盖 所以在子组件样式中加入scoped
<style lang="scss" scoped>
子传父通过event
npm i --save axios
71.反向代理,别名 跨域
在vue.config.js中配置反向代理
// 配置反向代理
devServer: {
port: 8080, // 随便改端口号
proxy: {
'/api': {
target: 'https://i.maoyan.com',
host: '*.000*.com',
changeOrigin: true
// 路径修改,把、api替换成空。
// pathRewrite: {
// '^/api': ''
// }
}
}
}
73.一级路由
先在view中创建三个vue,然后再router中的index.js中设置,最后在app.vue中启用
74.重定向
在router中的index.js中添加
// 重定向。就是删除到8080后点击回车自动跳转到设置的films。 path:'/'
{
path: '*',
redirect: '/films'
}
75.声明式导航
router-link有两个写法,一个是3版本的,有一个是4版本的。 custom是自定义 v-slot是插槽
问题?声明式导航新老版本的差别对比
76.嵌套路由
二级路由和嵌套路由的区别
77.编程式导航
列表跳详情
这个会判断是某个模式进行跳转,支持不带 # 的跳转
重点注意push里面如果想传入id就要用tab上面的那个按键``
// 编程式导航
// location.href= '#/detail'
// 这个会判断是某个模式进行跳转,支持不带 # 的跳转
// this.$router.push('/detail')
// 跳转到对应id的详情界面
this.$router.push(`/detail/${id}`)
//this.$router指的就是main.js中的new Vue里面的东西
78.动态路由
在index中设置动态路由,然后在my-play中利用this. r o u t e r . p u s h ( ‘ / d e t a i l / router.push(`/detail/ router.push(‘/detail/{id}`)可以跳转到对应的id的页面,但是想要获取id需要this. r o u t e . p a r a m s . m y i d 。 而 且 要 注 意 route.params.myid。而且要注意 route.params.myid。而且要注意router和$route的区别。
//$router : 是路由操作对象,只写对象
//$route : 路由信息对象,只读对象
//在index中写
{
path: '/detail/:myid', // 动态路由
component: detail
},
注意 r o u t e r 和 router和 router和route的区别
79.命名路由
{
name: 'nihaodetail', // 命名路由
path: '/detail/:myid', // 动态路由二级路由
component: detail
},
80.路由模式
在index中添加mode:‘history’。。使用history模式时,url没有 #,这样浏览器就会默认为是后端路由请求,有#时前端路由请求。极其容易出bug。。。
https://router.vuejs.org/zh/guide/essentials/history-mode.html#html5-%E6%A8%A1%E5%BC%8F
为什么有时候添加history:1. 好看 2. 公司要求 3.分享的时候有些软件会自动加上#,会出现问题。
不过,问题来了。由于我们的应用是一个单页的客户端应用,如果没有适当的服务器配置,用户在浏览器中直接访问 https://example.com/user/id,就会得到一个 404 错误。这就丑了。不用担心:要解决这个问题,你需要做的就是在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的 index.html 相同的页面。漂亮依旧!
81.全局路由拦截
在index中添加一下代码进行路由拦截
// 全局拦截(到哪去,从哪来,继续)
router.beforeEach((to, from, next) => {
console.log(to)
if(判断几个需要授权的路由){
if(授权通过){
}else{
next('/login')
}
}else{
next()
}
})
81.全局拦截和局部拦截
https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%90%8E%E7%BD%AE%E9%92%A9%E5%AD%90
83.路由懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效。
当项目过大的时候,第一次加载比较慢,所以为了解决首次加载过慢才用的懒加载
https://router.vuejs.org/zh/guide/advanced/lazy-loading.html
// 在上面不用添加这个import xx from '@/xxx'
{
path: '/order',
component: () => import('@/views/yyOrder.vue'), // 路由懒加载
}
图片懒加载
- 方法一:事件监听,利用滚动事件监听,利用forEach,如果图片距离视窗顶部的距离小于窗口显示区的高度,就要进行加载图片
- 方法二:intersectionObserver(交叉观察)浏览器提供的
84.rem回顾
在public中的index.html中添加
<script>
// fontsize计算
document.documentElement.style.fontSize=document.documentElement
.clientWidth/750*100+'px'
</script>
86.swiper组件
.eslintrc.js中加入’no-new’: 'off’就可以取消no-new提示。
安装最新版本的swiper在进行import 'swiper/swiper-bundle.css’操作的时候报错
npm i swiper@6.7.5 --save 安装
import Swiper from 'swiper/bundle' // 引入swiper 由于版本更新,所以+/bundle是swiper全部导入
import 'swiper/swiper-bundle.css' // 6.0
在进行swiper的制作的时候我们需要把模板写好,在FilmSwiper.vue中航你写好主体模板,然后在FilmSwiperItem.vue中写好每张图片的插槽,最后就是在myFilms.vue中把获取数据并导入进去。
88.选项卡的封装
方法1. 把iconfont放入public文件夹中,只需要在public中的index.html中进行引用就能使全局都可以用
方法2. 把iconfont放入src的asserts中然后直接在需要引用的界面中通过import进行引用。
import '../../assets/iconfont/iconfont.css'
声明式导航3样式中使用flex:1功能不能实现,用4可以实现
90.正在热映获取数据
fehelper前端助手浏览器插件
91.正在热映渲染
注意:列表到最小面的时候会有一个列表的部分被遮挡
92.详情数据
如果,那么这个class能够传递到film-header组件的父节点上
吸顶功能position: sticky;这是在myFilms.vue中添加的
制作详情页,在detail.vue中
要十分注意,在进行${}的时候一定要用``符号
axios({
url: `https://m.maizuo.com/gateway?filmId=${this.$route.params.id}&k=1758332`,
headers: {
'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.0","e":"1645712910171918950924289","bc":"110100"}',
'X-Host': 'mall.film-ticket.film.info'
}
}).then(res => {
console.log(res.data)
})
93.axois封装
封装方案一:新建一个util文件,创建http.js,然后把axios封装进去
封装方案二:https://www.axios-http.cn/docs/instance
94.详情页渲染
data.now()显示出来的是时间戳
95.详情页渲染2
动态class和静态class可以合并
97.详情轮播
当使用同一个轮播插件,但是使用的时候显示不同的个数就会出现问题。
在每个使用的上面添加不同的名字,参数的来回传递。
98.详情header组件
要注意层级关系,,防止覆盖底部导航栏z-index:**;
在详情页面detail.vue中添加
使用指令的时候要注意使用过后销毁
// !定义指令 绑定在谁的身上就可以拿到谁的原生DOM节点
Vue.directive('scroll', {
// inserted只会调用一次
inserted(el, binding){
// console.log(el)
el.style.display = 'none'
// 监控滚动事件
window.onscroll = () => {
console.log('scroll')
if ((document.documentElement.scrollTop || document.body.scrollTop) > binding.value){
el.style.display = 'block'
} else {
el.style.display = 'none'
}
}
},
// 销毁执行的
unbind(){
window.onscroll = null
}
100.影院组件渲染
如果列表过长,加载的时候会卡顿,怎么进行优化?
101.影院组件优化
安装better-scroll组件,这是列表优化组件
ref:绑定在什么身上就可以拿到对应的对象
// 动态计算高度
this.height = document.documentElement.clientHeight - document.querySelector('footer').offsetHeight + 'px'
102.elementUI组件库
npm i element-ui -S
在PCApp.vue中通过如下代码引入
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
103.vant引入
# Vue 3 项目,安装最新版 Vant
npm i vant
# Vue 2 项目,安装 Vant 2
npm i vant@latest-v2
在App.vue中使用如下代码引入
import Vue from 'vue'
import Vant from 'vant'
import 'vant/lib/index.css'
Vue.use(Vant)
104.vant应用
在detail中插入图片预览
https://vant-contrib.gitee.io/vant/#/zh-CN/image-preview
105.数据懒加载-1
list https://vant-contrib.gitee.io/vant/#/zh-CN/list
滚动加载,然后判断滑动的位置,根据滑动位置和可视窗口的位置来判断加载。这里采用的是vant组件库的list加载状态
注意数据懒加载分页时的数据合并。my-play.vue
// ...数据的展开合并【老数据展开,新数据合并】
// ....扩展语法。对数组和对象而言,就是将运算符后面的变量里东西每一项拆下来。
this.datalist = [...this.datalist, ...res.data.data.films]
106.数据懒加载-2
制作会出现:当点击到详细的页面的时候,出现滚动条的时候也会使列表页面触发滚动条
loading加载和axios拦截器
axios拦截器
https://github.com/axios/axios#interceptors
// 在请求之前拦截---showLoading
// 在发请求之前可以传一些数据过去
http.interceptors.request.use(function (config) {
// 加载提示
Toast.loading({
message: '加载中...',
forbidClick: true,
duration: 0
})
// ****
console.log(config)
return config
}, function (error) {
return Promise.reject(error)
})
// 在成功之后拦截---hideLoading
// 比.then早
http.interceptors.response.use(function (response) {
// 清除Toast
Toast.clear()
return response
}, function (error) {
return Promise.reject(error)
})
108.city组件数据
例如点击事件@click,这些在组件中是不能用的,需要查看文档说明,一般情况下点击事件是通过this.$emit(click)传递
注意写标签的时候‘/’斜杠也不能忘记
109.city数据转换
forEach循环特点和filter的特点
111.vuex引入
当在多个页面中都需要用到数据的时候使用vuex最方便
// !传统多页面方案传递数据
// location.href = ' #/cinemas?cityname=' + item.name
// cookie,localStroage
// !单页面方案
// 1.传统的中间人模式
// 2.bus事件总线方案
112.vuex同步工作流
vuex设置是在main.js和store中的index.js引入
在index.js中设置state公共状态,然后在外部就可以通过this.$store.state.***进行访问和修改
但是在使用公共状态的时候不容易溯源,因此要加上监控
this.$store.commit('changeCityName', item.name)
https://vuex.vuejs.org/zh/#%E4%BB%80%E4%B9%88%E6%98%AF%E2%80%9C%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%A8%A1%E5%BC%8F%E2%80%9D%EF%BC%9F
给浏览器安装vue插件
113.vuex异步引入
vuex管理保存公共状态(分散在各个组件内的状态统一管理。。在内存中管理,所以刷新后内存的数据会被清空)
不同组件之间是怎么传递信息的,例如在影院界面中,点击搜索怎么才能获取搜索的数据,以及在搜索界面刷新后怎么怎么获取数据。
采用vuex的异步
114.vuex异步应用
在 store文件中的index.js
步骤:首先在cinemas中利用 --异步同步actions的分发
this.$store.dispatch('getCinemaData', this.$store.state.cityId)
(这个要加if (this.$store.state.cinemaList.length === 0)防止每次刷新都调用)
然后把数据传送到store>index.ts的actions中,通过this.$store.state.cityId获取对应城市的id号,然后利用
store.commit('changeCinemaData', res.data.data.cinemas)
把数据传入mutations中的changeCinemaData函数中,通过state.cinemaList = data把数据存储到state公共状态中的cinemaList,这样就获取到了缓存的数据
commit是用来把数据传送到mutations中的,具体的看官网的图解
116.影院搜索组件
- vuex只能集中到一个store中
- 提交mutation是更改状态的唯一方法,并且这个过程是同步到的
- 异步逻辑都应该封装到action中
117-vuex新写法
vuex有两种写法
第二种需要在需要使用的文件中导入import { mapState, mapActions } from ‘vuex’
然后再写一个
/* 等同于cinemaList:function(){
return this.$store.state.cinemaList
}
*/
// !vuex写法二
// 这种只能获取state里面的东西
...mapState(['cinemaList', 'cityId'])
}
state是状态,可以放在计算属性里面,但是actions中的方法不能放在计算方法里面,这个时候我们可以放在methods里面,写法和上面一样
118.vuex控制底部选项卡
vue混入mixin()
https://cn.vuejs.org/v2/api/#extends
119.vuex持久化
安装vuex-persistedstate数据持久化插件
npm install vuex-persistedstate --save
// 在store的index中添加下面代码
import createPersistedState from "vuex-persistedstate"
const store =newVuex.Store({
plugins: [createPersistedState()]
})
https://www.jianshu.com/p/04c288731819
121.git本地仓库
仓库的创建使用
# git全局设置
git config --global user.name "guan0624"
git config --global user.email "gs1417@qq.com"
# 创建git仓库
// mkdir test002
// cd test002
git init
// touch README.md
// git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/guan0624/test002.git
git push -u origin "master"
# 已有仓库
// cd existing_git_repo
git remote add origin https://gitee.com/guan0624/test002.git
git push -u origin "master"
常见git命令
:wq用于错误时退出
git init
初始化本地仓库git add .
添加到暂存区git status
查看git此时的提交状态git commit -m '注释'
提交到本地仓库git log
查看记录 进入之后如果出现:则按q或Q退出git reset --hard HEAD^
回退到上一个版本git reset --hard HEAD^^
回退到上两个版本git reset --hard HEAD~1
回退到上一个版本git reset --hard HEAD
历届版本号git reflog
操作记录git push origin master
传到git服务器git pull origin master
拉取服务器的数据git remote add [shortname] [url]
添加远程版本库
组长要开通权限,然后成员才能下载
git clone 地址
,然后就下载下来了
git的使用
git pull origin master
获取之前更新的所有数据- 编写代码后使用
git add .
添加到暂存区 - 使用
git commit -m ''
提交到本地仓库 - 当需要获取上一个版本的数据的时候使用
git reset --hard HEAD^
即可,这时代码就会恢复到上一个数据的状态,然后再执行123。 - 完成后通过
git push origin master
上传到git服务器上 - 当上传的两者冲突的时候通过
git pull origin master
拉取服务器上的数据,然后进行更改获取需要的数据,然后再执行1、2、3、5就行了。
125.git分支的使用
git branch -a
查看分支git checkout -b ''
创建新分支git checkout 对应分支名
切换到对应的分支上git merge 需要合并的分支
合并分支git push origin :要删除的分支的名字
删除服务器分支git branch -d 分支名字
删除本地服务器的分支
128.nginx
nginx必须放在没有中文的路径
- 把项目文件dist拉入到nginx文件夹中
- 在nginx文件中的conf文件夹的nginx.conf复制一份,修改其中的数据
- 使用命令面板
.\nginx.exe -c .\conf\guan.conf
开启 .\nginx.exe -s stop
关闭.\nginx.exe -s reload
关闭
130.vue3项目改造
jsconfig.json显示有错的时候可以通过设置里面输入json找到那个,然后勾选就行了
// 重命名就是使用这种重定向的方法进行使用
{
path: '/:any',
redireact: {
name: 'films'
}
},
{
path: '/film',
component: Film,
name: 'films'
}
vue3中的重定向原来的不能用。
{
// vue3这个不能用
path: '*',
redirect: '/film'
}
vue3新加了一个hooks写法