b站看的视频,来做个总结
视频地址: https://www.bilibili.com/video/BV18A411J7QT?p=21&spm_id_from=pageDriver
技术选型
- vue + vue-router
- 网络请求 axios
- 样式布局: vant + less + vw/vh + flex + 百分比布局
- 存储 locallstorage
个人人为的的技术知识点
路由
路由赖加载
const login = ()=> import ('../views/login')
{
path: '/login',
component: login,
}
路由权限校验
// 利用导航守卫控制访问权限和动态标题
router.beforeEach((to, from, next) => {
/* 路由发生变化修改页面title */
if (to.meta.title) {
document.title = to.meta.title // 页面标题的展示
}
const tokenStr = window.localStorage.getItem('Mail')
if ((to.path === '/login' || to.path === '/registered') && tokenStr) {
// console.log('啥也不缺,直接调到主角面')
return next('/create')
}
if (to.path === '/login' || to.path === '/registered') return next()
if (!tokenStr) return next('/login')
// 如果输入主界面地址,但是无token,则返回登录页
next() // 最后一定要next一些
})
对于input的封装
<template>
<div>
<van-field
v-model="text"
:label="label"
:placeholder="placeholder"
:rule="rule"
:type="type"
autofocus
/>
</div>
</template>
<script>
export default {
props: ["label", "placeholder", "rule", "type"],
data() {
return {
text: "",
};
},
methods: {},
watch: {
text() {
this.$emit("handleChange", this.text);
},
},
};
</script>
<style lang="less" scoped>
</style>
使用
<login-text
label="账号2"
placeholder="请输入账号"
rule="^.{6,16}$"
@handleChange="(res) => (model.username = res)"
></login-text>
精妙之处,刚开始说输入框,我想到的是监听事件,来观察输入的参数
但是用watch来监听绑定的数据,真的是太棒了。并且将数据通过$emit给父组件传过去。父组件接收也很棒。 @handleChange = res => model.username
这样有个好处,就是每一个输入框,都能接收到正确的数据
如果按照传统的写法
@handleChange = handleChange
handleChange (res) {
this.model.username = res // 这样你根本不知道传来的数据跟输入框的数据是怎么对应的,你还得用三个事件来接收
}
插槽的使用
为什么用插槽: 有的数据是一样的,那么封装组件就可以写,有些数据是不一样的,那么就要用插槽,来自定义数据
比如这样
左边都是一样的,组件统一处理,但是右边需要显示数字,字符串,图片,这么多不确定因素,那就得使用插槽
定义具名插槽
<slot name="right"> </slot>
使用
<div name="right"></div>
上传组件的处理
<van-uploader :after-read="afterRead" />
这有一个问题,就是组件本来是这样的
但是,我要的是这样的
给他包一层,透明度0.宽度100vw 。position absolute
父元素,overflow:hidden position: relative
<div class="uploadfile">
<div class="uploadimg"><van-uploader preview-size="100vw" :after-read="afterRead" /></div>
<edit-banner left="头像">
<img :src="model.user_img" slot="right" alt="" v-if="model.user_img">
<img src="@/assets/default_img.jpg" slot="right" alt="" v-else>
</edit-banner>
</div>
.uploadfile{
overflow: hidden;
position: relative;
.uploadimg{
opacity: 0;
position: absolute;
}
}
上传完图片记得再次请求接口,因为现在只是前端展示,并不是后端真正的数据
传值: 字符串
父组件 left =“222”
子组件
传字符串
父组件 left=“222”
子组件
vant其他组件的调用
<div class="edit-banner" @click="handleEdit">
<div>{{ left }}</div>
<div>
<slot name="right"></slot>
</div>
</div>
</template>
<script>
export default {
props: ["left"],
methods: {
handleEdit() {
this.$emit("handleEdit");
},
+++++++++++++++++++++++++
<edit-banner left="姓名" @handleEdit="isGener = true">
<div slot="right">李四</div>
</edit-banner>
<div class="upload-file">
<div class="upload-img">
<van-uploader :after-read="afterRead" preview-size="100vw" />
</div>
<edit-banner left="上传头像" @handleEdit="isVantor = true">
<div slot="right">
<img src="" alt="" />
</div>
</edit-banner>
</div>
<edit-banner left="昵称" @handleEdit="ismodel = true">
<div slot="right">小花</div>
</edit-banner>
<div class="editback" @click="$router.back()">返回个人中心</div>
<van-action-sheet
v-model="isGener"
:actions="actions"
@select="onSelect"
cancel-text="取消"
close-on-click-action
@cancel="onCancel"
/>
<van-dialog v-model="ismodel" title="标题" show-cancel-button>
<van-field v-model="value" placeholder="请输入用户名" />
</van-dialog>
</div>
一些适配的单位
传统px,em,%
px:
em: 继承父元素字体的大小
rem: 相对于根元素html ()
vw: 相对于视图的窗口
% :父元素
对特定页面的缓存
有的页面需要缓存,有的页面不需要缓存(刷新之后,任然保持原来状态)
在router里:
meta:{
keepalive: true
}
在app.js里
<keep-alive v-if ="$route.meta.keepalive">
</App>
</keep-alive>
<router-view v-if="!$route.meta.keepalive"></router-view>
对数据的改造
const res = res.data
this.getData = this.changeCategory(res)
changeCategory(data) {
const q = data.map((item,index)=>{
item.XXX = xxx
return item
})
return q
}
监听路由的变化
watch:{
$route(){
this.getData()
}
}
input
递归数据
思路: 现在数据是平级关系,为null则是一级评论。下面则是coment_id 和parent_id的对应关系
先来看一个简单的递归
自己调用自己,并且有终止条件
一张纸的厚度是0.1mm, 对折多少次,他的厚度可以是1000mm
let a = 0.1
let num = 0
function n () {
a*=2
num++
console.log(num)
if (a< 10000) {
fn()
}
}
对数据的删除添加
先添加后删除
this.del.push(this.new[index])
this.new.splice(index, 1)
对标签数据的显示,是通过存储的形式显示的,配合监听属性
watch:{
newCat () {
localStorage.setItem('newCat', JSON.stringify(this.newCat))
localStorage.setItem('delCat', JSON.stringify(this.delCat))
}
}
created() {
if(localStorage.getItem('newCat')&&localStorage.getItem('delCat')) {
this.newCat = JSON.parse(localStorage.getItem('newCat'))
this.delCat = JSON.parse(localStorage.getItem('delCat'))
return
}
this.SelectCategory()
直接路由跳转
@click = “$router.push(’/edit’)”