Internship summary

五月

  1. Flex布局
  2. 阿里图标的使用; 引入到main.js文件供全局使用
  3. 复习CSS; 去除链接下划线、锁进两个效果图、文字高度同照片高度; 字体设置为斜体
将字体设置为斜体;font-style: italic;
  1. 创建项目; npm install -g @vue/cli; vue create xxx; npm run serve
  2. 下拉代码的时候, 出现冲突的解决方案
git stash; 保存当前工作进度,能够将所有未提交的修改(工作区和暂存区)保存至堆栈,用于后续恢复当前工作目录(先保存当前的工作进度)
git pull (下拉操作)
git stash pop; 可以把刚才stash到本地栈中的代码pop到本地 (把一开始保存的工作进度弹出去即可)
  1. CSS样式重叠过多;使用!important 怼上去
  2. 箭头一类的视觉效果,最好使用字体图标
  3. 根据浏览器尺寸来动态展示元素大小,使用vw和vh来进行
  4. 退出登陆的流程
清除token
页面跳转 this.$router.push('/main')等
!!!退出登录的按钮,需要自己明确点击事件应该绑定在哪一个元素上面(绑定元素也可以绑定在范围更广的一块上)
  1. git pull = git fetch + git merge
git fetch; 从远程仓库下载最新的提交历史和对象,并将它们存储在本地仓库中的远程跟踪分支中.这个操作不会影响你本地仓库的任何文件,只是把最新的代码下载下来
git merge; 将本地仓库中的当前分支与刚刚下载的远程跟踪分支进行合并.这会将远程仓库中最新的更改合并到你的本地仓库中,从而更新你的代码 即: 下载最新的代码并将其合并到本地仓库中的当前分支中
  1. git push时报错error: failed to push some refs to ‘https://gitee.com/**.git‘的解决方案
原因: 可能是因为在手动修改了远程仓库的文件,导致一些文件在本地仓库与远程仓库上不一致,故而引发该错误;
解决方法:git pull -rebase origin master 将远程仓库同步到本地,然后再重新add、commit、push即可
  1. flex布局失效问题
对某个元素进行flex布局以后, 对该元素使用width和height确定大小时,没有什么作用,可以考虑是不是宽度和高度作用的元素不生效,可能需要将宽高作用在其子元素上;通过子元素来撑起整个盒子
  1. 手风琴菜单的实现往往从上到下, 通过v-if来控制对整个模块的显示与隐藏; 取反操作: this.isShow = !isShow;
  2. 对某个元素的类名进行切换,根据类名来展示两种不同形态
先获取元素,可以使用ref,也可以使用原生操作DOM的方法
let icon = document.getElementById('icon')
切换类名的方法: toggle
icon.classList.toggle('rotate')
  1. Vue2中的数据是不支持直接修改和删除的, 不同的数据有不同的是处理方式, 可以使用方法或者数组下标来实现
  2. 同一层如果有很多不同的组件不好抽取的话,可以在总的内容外边包裹一层div,将v-for书写在最外层div中,这样内部的json就可以层层套用;
 无非是添加一些判断语句,用来判断相关元素是否存在; 
 如果是想对里面每一层的元素进行操作,可以在内部使用多层数据处理
  1. 想要在一个div中书写两个点击方法,可以使用; 后面有改进
<div @click="method1" @click.stop="method2"></div>
  1. 在使用Vue2中的时候,如果传入的json数据是有两层的时候,在template模版中书写方法的时候,可以通过遍历的时候;(item, index) in arrData, 通过传入index1和index2来精确定位到json当中的数据; 对应项目工具模块那一块
  2. 使用js获取到一个字符串中第一个空格前的内容
let str = "Hello World"
let firstSpaceIndex = str.indexOf(" ")
let result = firstSpaceIndex !== -1 ? str.substring(0, firstSpaceIndex) : str
  1. 对于一种数据类型;是一个数组,数组里面是一个个对象,每一个对象里面有个属性又是一个数组.在对最内侧数组中的属性进行相关操作的时候;可以使用forEach() 来进行相关操作
this.data.forEach(i => i.nextData.forEach((o) => {
    if(o.title === innerText) {
        this.activeItem = o
    }
}))
  1. 多人开发的时候为防止开发冲突,需要设置分支; 次分支想要拿到主分支上的内容;
- 首先,确保你在当前分支上工作,可以使用 git branch 命令查看
- 更新你的主分支,确保与远程仓库上的最新内容保持同步
git checkout main # 切换到主分支
git pull origin/master main # 拉取最新的主分支代码
git pull origin master 
- 切换回你的目标分支,将主分支上的内容合并到当前分支
git checkout your-branch # 切换回你的目标分支
git merge main # 将主分支的内容合并到当前分支
- git 会尝试自动合并主分支的更改到当前分支,如果有冲突,需要解决冲突并手动提交合并的更改
  1. 监视属性! 对于一些用于控制组件的属性,比如 isShow 等,如果在组件中过于深入,可以通过监视属性的值,来根据某些条件,进而来判断相关的属性;进而控制更多的属性是否进行展示
  • 其中 oldValue 和 newValue 如果没有用到是可以不写的
watch: {
    isShowSfq: {
      handler() {
        this.firstItem.forEach((item) => {
          item.isShowSecond = false
        })
      }
    },
    findToolsStr: {
      handler() {
        if (this.findToolsStr.length === 0) {
          this.firstItem.forEach((item) => {
            item.isShowSecond = false
          })
        }
      }
    }
  },
  1. 复习Vue2中的watch属性
当被监视的属性变化时,回调函数自动调用,进行相关操作
监视的属性必须存在,才能进行相关的监视操作
监视的两种写法
	- new Vue 时传入 watch 配置
	- 通过 vm.$watch() 进行相关的监视操作
watch:{
    // 监视的属性就是data中存在的,这一点还是很关键的
    isHot:{
        // 初始化时候马上执行一次
        immediate: true, 
        handler(newValue, oldValue) {
            console.log('isHot被修改了', newValue, oldValue)
        }
    },
    // 可以一次性监视多个值;
    numbers: {
        deep: true, 
        handler() {
            console.log('numbers改变了')
        }
    },
    // 如果不开启深度监视的话,可以使用简写的形式
    isHot(newValue, oldValue) {
        console.log('isHot被修改了', newValue, oldValue)
    }
}
  1. 使用template绑定在我们主要元素的外面,在template上是不可以绑定点击事件等相关的内容
  2. 在Vue.js中, 使用.stop修饰符可以阻止事件冒泡,这意味着当点击子元素时,事件不会向父元素传播,从而避免触发父元素上的点击效果。这在您想要在父元素上执行相关动作,但又不希望点击内部元素时触发时非常有用。
  3. 点击某个按钮进行路由跳转操作,可携带参数
this.$router.push({ name:'template', params:this.activeItem })
  1. 事件委托
用于处理动态添加或移除的元素上的事件监听
原理:将事件监听器添加到元素的共同祖先元素上,然后通过事件冒泡机制捕获事件,并在合适的时候执行相应的处理函数
  1. 事件冒泡
- 是指在页面中触发某个元素上的特定事件后,该事件会向上层元素逐级传播,直到传播到文档根节点或被阻止
- 事件冒泡是浏览器实现的一种事件传播机制,基于文档树结构
- 当一个元素触发某个事件时,比如点击事件,首先会触发该元素上绑定的事件处理函数,然后该事件会继续传播到该元素的父元素,再传播到父元素的父元素,依此类推,直到传播到文档根节点。
- 通过事件冒泡机制,我们可以实现事件委托和事件监听的优化。例如,当有大量的列表项需要绑定点击事件时,我们可以将事件监听器添加到列表的父元素上,并通过事件冒泡来处理每个列表项的点击事件,避免为每个列表项都添加事件监听器,减少了代码量和内存消耗。
- 要阻止事件冒泡,可以在事件处理函数中调用事件对象的stopPropagation() 方法。这样会阻止事件继续向上层元素传播,从而停止事件冒泡。
  1. 事件委托和事件冒泡的区别
- 事件委托
	- 事件委托是一种事件处理的模式,通过将事件处理程序绑定到其父元素或更高层次的元素上,以便在子元素上触发事件时,事件会冒泡到父元素并由父元素上的事件处理程序来处理。
- 事件冒泡
	- 事件冒泡是浏览器处理事件的机制之一,当一个元素上的事件被触发时,它不仅会在该元素上触发,还会从该元素开始沿着 DOM 树向上冒泡到父元素,直至达到文档的根元素。
- 总结
	- 事件委托是一种利用事件冒泡机制来优化事件处理的方法。通过将事件处理程序绑定到父元素,可以减少绑定的数量,并且可以有效地处理动态添加的元素。事件冒泡则是浏览器中事件传播的一种机制,使得事件从触发元素向上层层传递,直到根元素。
  1. 在一个div上绑定两个点击事件(补前面的坑) 中间用分号隔开
<div v-for="(o, i) in topNav" :key="i" @click="rotateClick(o.id); active(o, i, activeIndex)":class="topNavItemClass(i)">
  1. 像Google字体这种全家字体想要在整个项目中使用, 需要把相关样式写在全局css文件中
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@500&family=Source+Sans+Pro:wght@900&display=swap');

body {
  font-family: 'Noto Sans SC', sans-serif !important;
}
  1. ?.可选链的使用
- 表示可选链操作符,
- 作用:用于访问对象的属性或调用对象的方法时,可以在链式访问中处理可能为空或未定义的中间值,避免引发错误
- 通常,在访问对象属性或调用对象方法时,如果中间某个属性为 null 或 undefined,在不使用可选链操作符的情况下,访问该属性或调用该方法会导致 TypeError 错误。
- 而使用可选链操作符 ?.,如果链式访问中的某个属性为 null 或 undefined,则表达式会短路并直接返回 undefined,而不会引发错误。
const obj = {
  prop1: {
    prop2: {
      prop3: 'value'
    }
  }
};

// 使用可选链操作符
console.log(obj?.prop1?.prop2?.prop3); // 输出: "value"

// 避免错误,当中间属性为 null 或 undefined 时返回 undefined
console.log(obj?.prop1?.prop2?.prop4); // 输出: undefined

// 可选链操作符还可以用于函数调用
const func = obj?.method?.(); // 如果 obj.method 存在且为函数,则调用它
- 总结:处理对象的深层次属性访问时特别有用,减少了需要编写大量的条件语句来检查属性的存在性的情况。
  1. 经常使用v-if容易引起页面的重绘, 推荐使用:class的书写方式里面可以书写一些表达式会自动计算
<i :class="['iconfont', itemNext.isCollect ? 'icon-xingxingshixin' : 'icon-xingxingkongxin']"></i>
  1. 一个类下面有很多重复的元素,想要对某个重复的元素进行选择,可以通过伪类选择器来进行
.text-style span:nth-child(1n) { color: #340c65; }

.text-style span:nth-child(2n) { color: blue; }

.text-style span:nth-child(3n) { color: rgb(247, 200, 147); }

.text-style span:nth-child(4n) { color: rgb(55, 142, 55); }
  1. 本地的git无法获取到别人新创建的分支,可能的情况
- `远程分支未拉取到本地`:在执行 git branch -a 命令时,可以查看本地和远程的分支列表。如果远程分支没有被拉取到本地,你可以使用 git fetch 命令来获取最新的远程分支信息,然后再执行 git branch -a 查看是否能够获取到远程分支
- `远程仓库未关联`:如果你在本地克隆了一个全新的仓库,并且还没有与远程仓库建立关联,那么你是无法获取到远程分支的。你可以使用 git remote add origin <远程仓库地址> 命令将本地仓库与远程仓库关联起来,然后再执行 git fetch 命令获取远程分支信息
- `访问权限限制`:如果你没有权限访问远程仓库或者对应的分支,那么你将无法获取到远程分支。确保你有正确的权限,并且已经使用正确的认证方式(如用户名和密码、SSH 密钥等)进行了身份验证
  1. Vue模版中,template那一块,对于data中的数据是可以直接获取的, 不需要this.
  2. 在Vue2中,要实时监听到页面宽度的变化,需要使用到Vue中的watch和window.onresize监听事件

一般事件监听是添加在mounted钩子上,而且当监听完成以后,需要在组件销毁之前解除事件监听

mounted() {
    window.addEventListener('resize', this.handleWindowResize) // 其中resize事件通常是用来监听页面窗口大小的
}
beforeDestroy() {
    window.removeEventListener('resize', this.handleWindowResize)
}
  1. 账号密码设置时候; 一般会将手机号验证、密码验证、验证码验证抽取到一个公共方法中

密码在进行设置的时候,密码和确认密码不仅需要相同,而且要不为空,这样才能进行跳转操作;手机号和密码还需要进行相应的格式验证操作
在进行密码的验证登录时候,进行匹配的时候都是使用正则表达式的形式来进行判断验证; 而且在根据不同形式的输入密码进行显示不同的提示信息的话;需要控制好相关的变量; 如点击验证之后的操作

finishSetPD() {
    let hasLetter = /[a-zA-Z]/.test(this.newPD);
    let hasNumber = /\d/.test(this.newPD);
    let hasSymbol = /[!@#$%^&*]/.test(this.newPD);
    let validCombination = (hasLetter && hasNumber) || (hasLetter && hasSymbol) || (hasNumber && hasSymbol);
    if (this.newPD.length < 6 || !validCombination) {
        this.isShowOne = true
        this.isValidOne = false
    } else if (this.newPD !== this.confirmPD) {
        this.isShowOne = false
        this.isValidOne = true
        this.isShowTwo = true
        this.isValidTwo = false
    }
    if (this.newPD !== "" && this.confirmPD !== "" && this.newPD === this.confirmPD) {
        this.$router.push({ name: "mainLogin" })
    }
}
  1. 想让某个标签属性过段时间消失,除了可以使用css,也可以使用js中的定时器,但是需要在组件销毁之前将定时器清除; 某个条件如果不符合的话,不想逻辑继续往下面写的话,可以使用return终止
export default {
    name: "ForgetPD",
    data() {
        return {
            iphoneNumber: '',
            isValid: true,
            isShowTip: false,
            timer: null
        }
    },
    methods: {
        goMain() {
            this.$router.push({ name: "mainLogin" })
        },
        goGetVeri() {
            const phoneNumberRegex = /^1[0-9]{10}$/
            this.isValid = phoneNumberRegex.test(parseInt(this.iphoneNumber))
            if (this.iphoneNumber.length > 0 && this.isValid) {
                this.$router.push({ name: "GetVeri" })
            }
            this.isShowTip = true
            this.timer = setTimeout(() => {
                this.isShowTip = false
            }, 3000);
        }
    },
    beforeDestroy() {
        clearTimeout(this.timer)
    }
}
</script>
  1. 一些全局公用的方法,如手机号验证,验证码验证,密码验证等方法;可以书写在Util文件夹下,然后在js文件中使用分别暴露的形式; 其中分别暴露的形式可以在引入的时候将方法另取一个名字(对应于38条)
export function isPhone(phone) {
    return /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/.test(phone)
}
// 在别的组件中供相关引用
import { isPhone, isVeri, isPwd } from '@/util/common'
  1. transform的使用; transform是一个CSS属性,用于在元素上应用转换效果,可以改变元素的位置、大小、旋转角度和形状等
- 相关属性; 
平移; transform: translate(50px, 100px) / transform: translateY(5%)
缩放; transform: scale(1.5)
旋转; transform: rotate(45deg)
斜切; transform: skew(30deg, 15deg)
  1. 组件的相关抽取; 可以将某一个某一个需要展示的内容,抽取成一个组件,需要展示的具体位置可以通过绝对定位和相对定位的操作来决定组件具体在哪一个位置进行呈现展示
  2. CSS当中的, "&"是一个特殊的符号,用于表示父级别选择器,通常用于嵌套的选择器中,用于引用父级选择器的上下文
.button {
    background-color: #fff;
    color: #000;

    &:hover {
        background-color: #caecea;
        color: #6ea8a4;
    }
}
解释:在这个例子中,.button 是一个类选择器,它定义了按钮的默认样式。而 &:hover 则是 .button 的父级选择器(也就是自身)加上 :hover 伪类选择器。这意味着当鼠标悬停在 .button 元素上时,应用 &:hover 中定义的样式,从而改变背景颜色和文字颜色。 因此,& 在这个上下文中可以被看作是父级选择器的占位符,用于将样式与父级选择器进行关联。这样可以方便地在嵌套的选择器中引用父级选择器的样式,避免重复书写选择器名称。
  1. flex的相关属性
将display:flex; 其默认的flex-direction:row; 表示弹性容器的子元素将水平排列
align-item: xxx; 其用于设置弹性容器中子元素的垂直对齐方式的CSS属性
  1. 鼠标小手的相关属性; cursor:pointer; 用于指定元素在鼠标悬停时显示的光标形状的属性,将鼠标光标的样式设置为一个小手指形状,以提示用户该元素可以响应点击或交互操作
  2. z-index:200; 其是一个CSS属性,用于控制元素在堆叠上下文中的层级顺序;具体而言, 其值越大表示元素在堆叠顺序中较高的层级; 需要注意的是,z-index属性只对设置了position属性值为absolute、relative、fixed的元素起作用
  3. vue组件中,可以data中配置相关数据的时候,其中某一个数据属性中可以放入函数,很重要!
items: [
    {
        icon: 'icon-yonghu2',
        title: '个人信息',
        size: 17,
        onClick: () => { }
    },
    {
        icon: 'icon-mima',
        title: '修改密码',
        size: 17,
        onClick: () => { }
    },
    {
        icon: 'icon-tuichu',
        title: '退出登录',
        size: 17,
        onClick: () => {
        clearToken()
        location.reload()
        }
    }
]
  1. 如果设置了相关的样式,但是显示器屏幕太大的时候,样式不能进行修改操作的话,可以使用 max-width: 1280px;
  2. 通过:qa! 在git上面显示结束
  3. 在设置样式的时候,想要设置的样式在下拉的时候不覆盖原有的样式, 可以使用绝对定位和相对定位 + z-index属性的值来确定(想要设置的样式)

六月

  1. 全局事件总线的使用(兄弟组件之间传递数据)
- 全局事件总线的使用,组件结构不复杂的时候,可以使用全局事件总线 的形式来处理
- 全局事件总线的使用步骤
1、 先在main.js中,安装全局事件总线(在main.js文件中进行安装操作)
// 创建vm
new Vue({
    el:'#app',
    render: h => h(App),
    beforeCreate() {
        Vue.prototype.$bus = this //安装全局事件总线
    },
})
2、发送数据的组件,通过$emit触发事件,传递参数(通过this.$bus.$emit()来触发,发送); 一般在methods中进行操作
methods: {
    sendStudentName(){
        this.$bus.$emit('hello',this.name)
    }
},
3、接收数据的组件,通过$on来接收参数(接收参数通过this.$bus.$on()来进行触发操作)
- 接收数据的组件,一般在钩子函数中获取,获取到了以后才能应用这些数据
mounted() {
		// console.log('School',this)
		this.$bus.$on('hello',(data)=>{
			console.log('我是School组件,收到了数据',data)
		})
	},
4、 在组件接收数据以后,不用的时候,需要将注册的该数据取消; $off
beforeDestroy() {
		this.$bus.$off('hello')
	},
  1. Vuex的使用
组件想取到不同的store中的数据,可以通过计算属性来进行获取, 然后通过this.$store.state.XXstoreXX名字.XX属性名字; 写法
computed:{
    phoneNumber() {
        return this.$store.state.setPd.phoneNumber
    }
}
- 在进行设置一个vuex中的store的时候,可以使用主文件夹下面的index.js来直接全部进行暴露操作,
- 书写了一个store仓库
const state = { phoneNumber: "", veriCode: "", newPassWord: "" }

const mutations = { SETPHONENUMBER(state, phoneNumber) { state.phoneNumber = phoneNumber } }

const actions = { setPhoneNumber({ commit }, phoneNumber) { commit('SETPHONENUMBER', phoneNumber) } }

const getters = {

}
export default { state, mutations, actions, getters }
- 在主文件夹下面的index.js引入该文件并暴露出去,默认爆出
import setPd from './setPd'
export default new Vuex.Store({ modules: { setPd, user.. } })
  1. Vue2组件中从vuex中获取到的数据是直接绑定到组件实例身上的data对象上的
  2. Vue3的响应式数据
- 可以使用ref和reactive函数来创建响应式数据,但是适应类型不同
- ref主要用于创建包装基本类型的响应式数据;例如:一个数字、字符
const count = ref(0)
const message = ref('hello')
- reactive主要用于包装对象或者数组的响应式数据,
const state = reactive({
    count: 0, 
    message:'hello', 
    items:['banana', 'apple', 'orange']
})
- 这里的state对象及其属性都是响应式的,当其中的属性值发生改变时,相关的界面 元素也会同步更新.
  1. vuex中,dispatch参数的传递
this.$store.dispatch('方法名', 携带的数据参数)
如果为多个参数,携带的数据参数弄成对象的形式
  1. 详解Vuex中的四大属性

state(状态)
getters(获取器);允许你获取state值之前进行一些计算或处理
mutations(突变);用于修改State的唯一途径;其是同步函数,用于处理同步状态的变更操作
actions(动作);用于处理异常操作或复杂业务逻辑,在各个组件中,可以通过分发(dispatch)一个Actions,执行异步操作;在actions中,最终通过提交一个Mutation来修改State,
调用接口的操作; actions中,可以直接解构出{ commit }, 然后满足条件以后进行commit操作,可以直接对数据进行处理,保存等

const actions = {
    // 获取验证码,注册
    async getCode({ commit }, { phoneNumber, type }) {
        if (type === 2) {
            const param1 = { "phone": phoneNumber }
            let result = await getVerificationCode(param1, type)
            if (result.code === 0) {
                commit('GETCODEFORREGISTER', result.data)
                return 'OK'
            } else {
                return Promise.reject(new Error('服务器异常'))
            }
        } else if (type === 3) {
            const param2 = { "phone": phoneNumber }
            let result = await getVerificationCode(param2, type)
            if (result.code === 0) {
                commit('GETCODEFORFORGETPD', result.data)
                return 'OK'
            } else {
                return Promise.reject(new Error('服务器异常'))
            }
        }
    },
    // 重设密码
    async resetPD({ commit }, user) {
        console.log(user)
        let result = await resetPassword(user)
        if (result.code === 0) {
            return 'ok'
        } else {
            return Promise.reject(new Error('服务器异常'))
        }
    },
    // 用户登录
    async userLogin({ commit }, user) {
        let result = await saveUser(user)
        if (result.code === 0) {
            let loginResult = await loginCallback(result.code)
            commit('USERLOGIN', result.data.token)
            setToken(result.data.token)
            return 'ok'
        } else {
            return Promise.reject(new Error('fail'))
        }
    }
}
  1. input框中,鼠标移入,input框中的提示词消失
input:focus::placeholder {
    color: transparent;
}
  1. 滚动条的操作: 为了页面能够更加的美观,通常将滚动条进行隐藏操作;操作;当然父标签中需要写上overflow-y:auto;
&::-webkit-scrollbar {
    width: 0px;
}
  1. 想要根据浏览器窗口大小,实时检测窗口大小,根据窗口大小动态判断某个图标是否展示等
- 首先在data中定义一个变量
- 在组件进行挂载的时候,
mounted() {
    window.addEventListener('resize', this.handleWindowResize)
},
beforeDestroy() {
    window.removeEventListener('resize', this.handleWindowResize);
},
- 定义的该方法,在methods中进行书写;将页面中的窗口大小随时更新到data数据中
handleWindowResize() {
  this.pageWidth = window.innerWidth
}
- 通过watch来进行监视操作;而且,三元运算符往往可以代替if...else...语句
watch: {
    pageWidth(newValue, _) {
        this.isShowXiaLa = newValue < 1400 ? false : true
    }
},
  1. Vue2对象中添加响应式属性的操作
this.$set(this.obj, 'newProperty', 'value')
  1. 计算属性computed

computed计算属性获得的结果,最后是会挂载在组件实例身上,类似挂载在data上的数据
在vue.js2当中, 计算属性的简写形式的话,计算属性是只读的;无法直接在计算属性内部调用方法来修改计算属性的值
计算属性是根据其依赖属性的响应式数据自动计算得出的
要根据计算属性的值,来呈现;对于一个对象,初次想呈现第一个位置的元素;后续根据用户的点击来显示不同的元素,可以通过点击的下标传入过去,这样计算属性中的值就会自动更新 (在数据的沟通这一块,传输index太过于重要)

  1. 将模版更换elementUI的颜色类;根据产品的UI来决定;
  2. indexOf用于查找字符串或数组中指定元素的方法,返回位置索引,没有找到返回-1
const arr = [1, 2, 3, 4, 5];
const element = 3;
const index = arr.indexOf(element);

if (index !== -1) {
    console.log("元素存在于数组中");
} else {
    console.log("元素不存在于数组中");
}
  1. Vuex中的mutation
- 可以对state中的数据进行操控
GETTEMPLATEDATA(state, templateData) {
    state.templateData = templateData
}
- vuex中的actions文件中, 可以结构出{ commit, dispatch }
	- commit用于对state中的数据进行操控
	- dispatch用于调用本次vuex中,其他位置上的actions方法;
  1. 监视属性

监视属性watch也可以对计算属性中的值进行监视
监视属性往往可以用于监视的属性发生了改变,然后执行某种逻辑
因为在子组件中点击某个按钮,父组件中的数据没有实时更新,就需要用到监视属性,当监视到的属性,改变了,就执行某个方法执行;渲染页面的相关操作

  1. 子组件收到复组件传递过来的props数据;可以使用对象的形式进行书写;

以对象的形式来进行展示操作(对象里面也是一个个新的对象,每个对象有很多属性,比如类型、默认值等)

  props: {
    width: {
      type: Number,
      default: 221,
    },
    height: {
      type: Number,
      default: 192,
    },
    icon: {
      type: String,
      default: 'icon-gengduo'
    },
    title: {
      type: String,
      default: '案例研究概述'
    },
    content: {
      type: String,
      default: '聚焦客户以展示使用您的产品或服务的巨大成果。'
    },
    active: {
      type: Boolean,
      default: false
    },
    templateId: {
      type: String,
      default: "001"
    },
    nav: {
      type: Array,
      default: []
    },
    lickTempData: {
      type: Array,
      default: [],
    },
    isCollect: {
      type: Boolean,
      default: false
    },
  },
  1. 你点击事件在子组件上,那就一定要在子组件上书写相关的点击逻辑;
  2. 在Vuex中存了点击某个按钮进行收藏的功能

其实就是将某个模版的tempId保存到一个数组当中; 因为Vuex中的数据在别的地方也能拿到;
然后在TemplateBox组件中进行获取操作; 因为每次点击icon; TempDataID都会改变, 所以需要在TemplateBox组件中,实时监视TempDataID数组, 通过监视该值来决定 this.isCollect的值;

watch: {
    immediate: true,
    TempDataID(newValue, _) {
      // 判断每一个ID,根据每一个ID是否是TempDataID中的一个来判断isCollect的值;
      this.isCollect = newValue.includes(this.templateId) ? true : false
    }
  },
  1. @click.stop

用于事件处理的修饰符之一,用于阻止事件继续传播,即停止事件冒泡;
比如;点击某个收藏按钮;不会影响到大框框外面的东西;

  1. 如果想要动态展示某种类型的话,可以使用class类型的动态写法;(前面提及过)
:class="['iconfont', isCollect ? 'icon-xingxingshixin' : 'icon-xingxingkongxin']"
  1. 在vuex中书写接口方法的时候; 需要观察接口需要传入的数据是什么(尤其是后端接口的参数形式); 数据要么在actions方法中解构成后端接口的形式; 要么在组件中dispatch 调用vuex中的actions中的方法时候进行参数的调整;
> 将键值调整成后端需要的样子; 将键值对调整成后端接口的形式
try {
    // 相关的数据都是可以从this中解构出来;
    const { iphoneNumber, veriStr, newPd } = this
    // 相关的键名,其实和后端的设置有很大关系;而且密码通常都是经过是哈希过的
    const user = { phone: iphoneNumber, code: veriStr, password: AES.hashPassword(newPd) }
    await this.$store.dispatch("resetPD", user)
} catch (error) {
    console.log(error.message)
}
// 通常我们会在完成相关的操作以后,进行路由的跳转操作
this.$router.push({ name: "chat" })
  1. 数组中的forEach方法和includes方法
/* 
    1、用于检查数组是否包含特定元素,并返回一个布尔值
*/
// const array = [1, 2, 3, 4, 5];

// console.log(array.includes(3));  // 输出: true
// console.log(array.includes(6));  // 输出: false
/* 
    2、JS中的forEach方法
        - 用于对数组中的每个元素执行指定的函数
        - 不会改变原数组
*/
const array = [1, 2, 3, 4, 5];

array.forEach(function(element, index, array) {
  console.log("Element:", element);
  console.log("Index:", index);
  console.log("Array:", array);
});
  1. 想要某个属性一改变就影响其他属性,可以使用监视属性
  2. 在设置元素位置的时候,需要随着屏幕的宽度大小进行随时改变的时候,如果使用vh或者vw没有效果的时候,可以使用百分号
  3. 在Vue2中模版想要动态展示内容的时候,可以使用动态字符串的形式(非常关键)
{{ `${item.text}(${item.nextArr.length})` }}
  1. 整个工具模块; @click方法除了调用传入数组下标以外,还可以直接把整个对象或者数组传过去
  2. 查找某个元素是否存在的时候,可以使用数组some和find方法会比较好
  3. 对于项目中在控制台没有必要的警告,可以通过在main.js中,添加一句代码; Vue.config,silent = true
  4. 数组中的find、some、filter方法
// 1、find方法
const arr = [1, 2, 3, 4, 5];
const result = arr.find(num => num > 3);
console.log(result); // 输出4
// 2、some方法
const arr = [1, 2, 3, 4, 5];
// 判断数组中是否存在偶数
const hasEvenNumber = arr.some((element) => element % 2 === 0);
console.log(hasEvenNumber);  // true
// 3、filter方法; 会返回一个新的数组
const numbers = [1, 2, 3, 4, 5];
const oddNumbers = numbers.filter(number => number % 2 !== 0);
console.log(oddNumbers);  // [1, 3, 5]
  1. Vue2中的this.$set()方法

其可以动态的添加或修改Vue实例中的响应式属性
用法;后面两个必须是字符串的形式

this.$set(this.someObject, 'newProperty', 'new value');
  1. 对象和其中的相关属性进行合并操作; 可以使用解构赋值的写法;
this.firstItem[1]?.nextArr.push({ ...this.firstItem[index1]?.nextArr[index2], id: getUUID() })
  1. 主页导航栏左边的菜单是通过activeIndex属性来决定的; 在跳转的时候需要精准跳转的时候,需要及时定位activeIndex的值
  2. 父子组件通信最简单的形式是通过props来传递属性操作的;
- 父组件中,通过在子组件标签上定义属性来传递数据; 子组件可以像本地数据一样使用props属性
<template>
    <div>
        <child-component :message="message"></child-component>
    </div>
</template>
- 子组件中,通过props选项来声明接收的属性; 
<template>
    <div>
        <p>{{ message }}</p >
    </div>
</template>

<script>
export default {
        props: ['message']
    }
</script>
  1. 如果某些属性每次点击都会重复计算,导致效果不行,需要每次运行的时候将存储数据的结构重置
this.userCollect = []
  1. Vue项目中,刷新页面后,页面中操作的数据信息被重置了怎么进行处理?

解释: Vue.js中的数据是存储在内存中的, 而不是持久化保存在页面或服务器上,
如果希望在页面刷新之后保留数据方法

1、使用浏览器的本地存储(LocalStorage)或会话存储(SessionStorage); 在组件的生命周期钩子(created)中,把数据保存到本地存储或会话存储中,在页面加载时,从存储中读取数据并重新设置到组件中
// 在created钩子中保存数据到本地存储
created() {
    const data = JSON.stringify(this.yourData);
    localStorage.setItem('yourData', data);
},

// 在mounted钩子中从本地存储中恢复数据
mounted() {
    const data = localStorage.getItem('yourData');
    if (data) {
        this.yourData = JSON.parse(data);
    }
}
2、使用后端服务器进行数据持久化: 如果需要将数据保留在多个会话或多个浏览器中,可以将数据存储在后端服务器上(数据库). 当页面刷新时,从服务器重新加载数据并将其传递给Vue组件
  1. 数组中的shift和unshift方法
/* 
    数组中的shift方法
        - 用来弹出数组的第一个元素
        - 返回删除数组的第一个元素
    - 会修改原来数组的值
*/
const arr1 = [1, 2, 3, 4, 5]
const firstElement = arr1.shift()
console.log(firstElement) // 1
console.log(arr1) // [ 2, 3, 4, 5 ]

/* 
    数组中的unshift()
        - 用于在数组的开头添加一个或多个元素
        - 并返回新数组的长度
*/
const arr2 = [2, 3, 4, 5]
const arr2Length = arr2.unshift(1, 3)
console.log(arr2Length)
console.log(arr2)
  1. 计算属性的值在首次访问后会被缓存;并且只有计算属性依赖的响应式数据发生变化时才会重新计算; 下面这种依赖的东西完全没有变化
userToken() {
    return window.localStorage.getItem('token')
}
  1. 有些数据虽然用到了响应式的操作,但是控制台没办法实时拿到,但是只有当用户刷新以后才能拿到, 可以通过下面方法拿到:同用户点击了浏览器的刷新按钮一样

浏览器自动刷新的方法
location.reload()是JavaScript中的方法,用于重新加载当前页面。它会导致整个页面被重新加载,包括所有的资源文件(如CSS、JavaScript等),并且会重置页面的状态。
这种就比较消耗页面的性能和资源了

  1. 登陆权限的问题

用于判断用户是否拥有了ID或者Token等数据情况;
用户拥有了这些数据再进行相关的操作;

  1. placeholder本来就是用户输入的内容传入此处;用户点击的话就在此处;是不占领任何位置的;

placeholder就是用户输入的内容传入此处
也可以对input框中的内容进行相应格式的设置

input::placeholder {
    font-family:"Noto Sans SC", sans-serif;
    font-size: 14px;
    color: #999;
}
  1. 点击获取验证码按钮,出现验证倒计时操作
  2. 点击某个按钮,后面进行不同内容的切换操作可以使用v-if/v-else来进行相关处理
模版字符串与{{ }} 想呼应处理 {{ `` }}的形式
  1. 倒计时获取验证码操作
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>获取验证码</title>
    <style>
      @keyframes countdown {
        0% {
          transform: scale(1);
          opacity: 1;
        }
        100% {
          transform: scale(2);
          opacity: 0;
        }
      }

      #countdown {
        font-size: 48px;
        text-align: center;
        margin-bottom: 20px;
        animation: countdown 60s linear infinite;
      }

      button {
        font-size: 16px;
      }
    </style>
  </head>
  <body>
    <div id="countdown">60</div>
    <button onclick="startCountdown()">获取验证码</button>
    <script>
      function startCountdown() {
        var countdownElement = document.getElementById("countdown");
        var countdownValue = parseInt(countdownElement.innerHTML);

        var countdownInterval = setInterval(function () {
          countdownValue--;
          countdownElement.innerHTML = countdownValue;

          if (countdownValue === 0) {
            clearInterval(countdownInterval);
            countdownElement.innerHTML = "";
            // 在这里可以添加获取验证码的逻辑
          }
        }, 1000);
      }
    </script>
  </body>
</html>
  1. 在vuex中, 如果想要在某个动作之后,获取到最新的数据, 需要在某个步骤以后重新发送数据的操作,这一点非常关键
  2. pinia操作数据的方式; 区别于Vuex
- 直接通过this.xxx方法来进行调用操作;
actions: {
    async postUsersListAction(queryInfo: any) {
      const usersListResult = await postUsersListData(queryInfo)
      const { totalCount, list } = usersListResult.data
      this.usersTotalCount = totalCount
      this.usersList = list
    },
    async deleteUserByIdAction(id: number) {
      // 1.删除数据操作
      const deleteResult = await deleteUserById(id)
      console.log(deleteResult)

      // 2.重新请求新的数据
      this.postUsersListAction({ offset: 0, size: 10 })
    },
- vuex中的操作手段 -- 因为不仅可以解构出commit还可以解构出dispatch
> 通过actions中的方法参数,解构出dispatch来进行调用相关的方法;
// 收藏模板
async collectTemplate({ commit, dispatch }, tempId) {
    let result = await lickTemp(tempId)
    // console.log(result)
    if (result.code === 0) {
        dispatch('getLickTempData')
    } else {
        return Promise.reject(new Error('服务器异常'))
    }
},

- Vue2中, 模版渲染和计算属性的执行顺序是在mounted生命周期钩子之后执行的; 在mounted钩子中,Vue实例已经被挂载到DOM,并且模版已经渲染完毕了
- created: 在Vue实例被创建后立即调用。在这个阶段,实例已完成数据观测、属性和方法的运算,但是尚未开始DOM编译和挂载。
	- 已经可以拿到计算属性中的值,
- 请注意,如果你在计算属性中依赖了异步数据(例如通过API请求获取的数据),则计算属性的值可能在mounted钩子之前不可用。在这种情况下,你可以考虑使用watch或者created钩子来处理异步数据。
	- 异步数据,通常是在watch和created中来进行处理
  1. 在Vue 2中,通过props将数据从父组件传递给子组件时,默认情况下是非响应式的。这意味着当父组件中的prop数据发生变化时,子组件不会自动更新来反映这些变化。
  2. 然而,Vue 2提供了一种方式来使props数据成为响应式的,即使用prop选项的sync修饰符。使用sync修饰符,可以将子组件对prop数据的修改反映回父组件中
<!-- ParentComponent.vue -->
<template>
    <div>
        <ChildComponent :message.sync="message" />
    </div>
</template>
  1. Vuex的再次总结

vuex中的数据是响应式的,用于管理应用程序的全局状态,当你在vuex中定义和修改数据时,数据会自动转化为响应式的;
vuex中会一直帮忙维护相关的数据,用于响应式,即相关数据更新,页面会跟着自动更新操作

当你通过store.state访问Vuex中的状态数据时,这些数据是响应式的。当你在组件中使用this.$store.state或使用辅助函数如mapState来获取状态数据时,当状态数据发生变化时,相关的组件将会更新。
当你在组件中通过this.$store.commit提交一个mutation来修改Vuex中的数据时,这些修改也会被追踪,以便Vue可以在必要时更新相关的组件.

在Vuex中,我们想要新的数据,可以在state中自己定义; 然后在mutations中进行相关的修改操作
vuex中, 想要在actions中调用其他的方法; 需要使用dispatch进行相关的派发操作; 而且一般是在**状态码返回成功的时候进行dispatch和commit的操作;
在某个组件中,获取vuex中的动态的数据,通常是在计算属性computed中进行获取
this.$store.state.xxxVuex名字xxxx.属性名

lickTempData() {
    return this.$store.state.getDataInfomation.lickTempData
},

七月

  1. 注册成功以后,跳转到首页,并自动登录

想要自动登录,就是跳转到首页之前将注册成功返回的token,设置到浏览器中即可

setToken(this.$store.state.user.token)
this.$router.push({ name: "chat" })
// 其中,这个token是来自vuex中的token,
// 用户登录
async userLogin({ commit }, user) {
    let result = await saveUser(user)
    if (result.code === 0) {
        let loginResult = await loginCallback(result.code)
        commit('USERLOGIN', result.data)
        // setToken(result.data.token)
        return 'ok'
    } else {
        return Promise.reject(new Error('fail'))
    }
}
  1. 双击事件 使用 @dblclick
<template>
  <div>
    <button @dblclick="handleDoubleClick">双击我</button>
  </div>
</template>

<script>
  export default {
    methods: {
      handleDoubleClick() {
        // 双击事件的处理逻辑
        console.log("双击事件触发!");
      }
    }
  }
</script>
  1. 子组件调用父组件的方法; 可以通过自定义事件来处理

某些一个个的空格在子组件身上,子组件身上的双击事件,然后触发父组件身上的方法,可以通过自定义事件来进行处理;

父组件
<TemplateBox @goTemplate="createProject"/>

子组件
<div :style="`width: ${width}px;height: ${height}px;`" :class="mainClass" @dblclick="goTemplate"></div>

methods: {
  goTemplate() {
    this.$emit('goTemplate')
  }
},
  1. 模版切换以后,内容还在; 使用watch属性来监视模版内容,一旦模版内容发生改变,将input和textarea框中的内容清除;
  2. 监听滚动事件;

可以通过ref = "msg"拿到具体的元素;
通过@scroll=“xxx” 来绑定滚动的相关方法操作
this.$refs.msgs.scrollTop 来获取滚轮的距离; – 滚动事件,实时获取滚动事件
滚动方法; 滚动到相应的位置; 通过调用相关方法来实现

scrollTop() {
  this.$refs.topMag.scrollIntoView({
    behavior:'smooth', // 平滑滚动
  })
}
  1. 倒计时方法的实现; 根据某个值的true或者false来控制某个页面的显示
<!-- 就是通过判断countdownActive的值是否应该出现 -->
this.countdownActive = true
const countdownTimer = setInterval(() => {
    this.countdown--
    if (this.countdown === 0) {
        clearInterval(countdownTimer)
        this.countdownActive = false
        this.countdown = 60
    }
}, 1000);
  1. 给input框和里面的提示词placeholder设置不同的字体;
input,
textarea {
    font-family: "Noto Sans SC", sans-serif;

    &::-webkit-input-placeholder {
    font-weight: 500;
    }
    &::placeholder {
    font-family: "Noto Sans SC", sans-serif;
    font-size: 14px;
    color: #999;
    }
}
  1. 连接分支; 出错

第一次连接主分支上的内容时报错

There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> master

解决方案;按照提示进行相关解决处理

git branch --set-upstream-to=origin/KangDemo master
  1. bind的两个作用;

生成新的函数; 想要验证可以用一个变量来进行接收
改变this的指向; react改变state的状态,需要使用到setState方法来进行处理
react中初始化状态一般都是使用简写的形势,不需要在构造器中进行相关调用操作!

- 针对react
组件的自定义方法中this为undefined,如何解决
> 强制绑定this,通过函数对象的bind();
> 定义的方法,使用箭头函数来实现!
  1. 展开运算符; 用于数组或对象时,可以展开数组或对象,将其元素或属性扩展到另一个数组或对象中。
    应用
1、 合并数组
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];
console.log(combined); // 输出: [1, 2, 3, 4, 5, 6]
2、 复制数组
function sum(a, b, c) {
    return a + b + c;
}
const numbers = [1, 2, 3];
const result = sum(...numbers);
console.log(result); // 输出: 6
3、传递数组元素作为参数
function sum(a, b, c) {
    return a + b + c;
}
const numbers = [1, 2, 3];
const result = sum(...numbers);
console.log(result); // 输出: 6
4、 剩余参数运算符
表示接收多个参数,并将它们作为数组保存在一个变量中
function sum(...numbers) {
    let total = 0;
    for (let num of numbers) {
        total += num;
    }
    return total;
}
console.log(sum(1, 2, 3)); // 输出: 6
console.log(sum(4, 5, 6, 7)); // 输出: 22
  1. 后端接口给好了,对工具栏数据重新进行设置;

其实只需要将vuex中的数据取出来进行相关展示即可
因为你本身进行点击操作的话,也会将数据传送过去

  1. 对data中某一块数据的属性进行修改
this.$set方法,参数值;
1、对象
2、对象中的属性(字符串形式)
3、需要赋的值
this.$set(item, 'isCollect', true)
  1. 收藏功能
收藏功能over
- 其实就是一开始的展示问题是一个大问题
- 无非就是根据isCollect的值来判定是应该收藏还是取消收藏
- 收藏和取消收藏的时候,需要调用接口来进行收藏和取消收藏,存入到数据库中进行存储!
  1. JSON的相关操作
const obj = {
    name: "John",
    age: 30,
    city: "New York"
};

const jsonString = JSON.stringify(obj);
console.log('jsonString', jsonString); //  {"name":"John","age":30,"city":"New York"}
console.log(typeof jsonString); // string 字符串的形式

const objNext = JSON.parse(jsonString)
console.log(objNext)
// typeof 直接使用即可 typeof something
console.log(typeof objNext) // object 
  1. localStorage的使用;
- localStorage是web浏览器提供的一种持久化存储数据的机制,可以用于在浏览器中存储和检索键值对数据
- 用法
	- 存储数据
	localStorage.setItem('key', 'value');
	- 检索数据; 通过直接获取来拿到;
	const value = localStorage.getItem('key');
	- 更新数据
	localStorage.setItem('key', 'new value');
	- 删除数据
	localStorage.removeItem('key');
	- 清空所有数据
	localStorage.clear();
  1. localStorage 和 sessionStorage有什么区别?
- 生命周期不同
localStorage:存储在localStorage中的数据没有过期时间,除非手动清除或通过代码删除,否则数据将一直存在。即使关闭浏览器或重新启动计算机,数据也会保留
sessionStorage:存储在sessionStorage中的数据仅在当前浏览器会话(即打开的浏览器标签或窗口)期间有效。当关闭浏览器标签或窗口时,sessionStorage中的数据将被清除。
- 作用域
localStorage:localStorage中的数据在同一个域名下的所有页面之间共享。即使在不同的页面上打开同一域名下的不同标签或窗口,它们可以访问和操作相同的localStorage数据
sessionStorage:sessionStorage中的数据仅在同一个浏览器标签或窗口中共享。不同的标签或窗口之间无法直接访问对方的sessionStorage数据
- 存储容量
localStorage和sessionStorage的存储容量通常相同,通常为几MB。可以自己进行相关配置
- 数据访问
  1. 会话技术

在公共暴露的方法JS中书写相应的方法
localStorageUtil.js

export function setProjectHistory(history) {
    window.localStorage.setItem(projectHistory, JSON.stringify(history))
}
export function getProjectHistory() {
    let o = window.localStorage.getItem(projectHistory)
    return o ? JSON.parse(o) : []
}

在组件中进行使用; 一般我们放在浏览器中的东西都是需要在页面进行直接展示的,一般放在生命周期created()中

let items = getProjectHistoryPlus()
items = items.map(o => JSON.stringify(o))
items = [...new Set(items)]
items = items.map(o => JSON.parse(o))
this.habit = items
this.firstItem[1].nextArr.push(...this.habit)
this.$nextTick(() => {
    this.firstItem[0]?.nextArr?.forEach(itemFirst => {
    this.firstItem[1]?.nextArr?.forEach(itemSecond => {
        if (itemFirst.text === itemSecond.text) {
        this.$set(itemSecond, 'isCollect', true);
        }
    })
    })
})
  1. 在vue组件的使用过程中,在模板中可以书写方法,传入的参数往往有 index等, 但是也可以直接传入某一个数组里面的对象,通过对象的内容来一次次完成即可
例如: this.firstItem[index1].nextArr[index2].text其实就相当于是itemNext.text,这一点非常关键,

因为在模板中可以传入很多东西进来

在组件模版中可以拿到很多东西,因为v-for进行遍历的时候有对象和索引,通过索引可以具体定位,也可以直接传入相关的数据;

拿到相应元素的ID,然后再进行相应操作,是Vue中常用的操作(拿到相应的key,然后进行相应操作也可以)

因为data中的数据都是响应式的,根据不同的索引来书写不同的内容
  1. 数组中的splice() 方法,splice() 方法可以用于添加、删除和替换数组中的元素
要替换数组中的元素,你可以指定索引位置和要替换的元素数量,然后提供新的值作为替换。
例如,假设你要将数组 arr 中索引为 index 的元素替换为新的值 newValue,可以使用以下代码:
参数2表示是否要删除,如果为0则表示的是替换,如果是数字1则表示的是删除,然后让后面的元素顶替
arr.splice(index, 1, newValue);
解释:这将删除索引为index的元素,然后将newValue插入到该位置 注意:这两种方法都会在原始数组上进行修改,而不是创建一个新的数组
  1. created钩子是在Vue组件实例被创建之后立即调用的
所以data数据是在created钩子之前就已经存在
可以在监视属性中一开始就进行相关数据的操作
  1. 模版ID的唯一性设置
对于id的设置唯一性,一级和二级的id不要重复即可,因为如果重复可能会导致数组循环发生错误
使用下面这种形式即可
firstItem: [
    {
        id: 0,
        text: '我的收藏',
        isShowSecond: false,
        isShowBorder: false,
        nextArr: []
    },
    {
        id: 1,
        text: '最近使用',
        isShowSecond: false,
        isShowBorder: false,
        nextArr: []
    },
    {
        id: 2,
        text: '热门工具',
        isShowRemen: true,
        isShowSecond: true,
        isShowBorder: true,
        nextArr: [
        {
            id: 100,
            text: '小红书文案',
            ExtraIcon: false,
            isCollect: false,
        },
        {
            id: 101,
            text: '公众号文案',
            ExtraIcon: false,
            isCollect: false,
        },
        {
            id: 102,
            text: '知乎文案',
            ExtraIcon: false,
            isCollect: false,
        },
        {
            id: 103,
            text: '百家号文案',
            ExtraIcon: false,
            isCollect: false,
        },
        {
            id: 104,
            text: '微博',
            ExtraIcon: false,
            isCollect: false,
        },
        {
            id: 105,
            text: '大众点评',
            ExtraIcon: false,
            isCollect: false,
        },
        ]
    },
    ...
 ],
最近使用这一块的制作,相关数据的保存放在浏览器当中
最近使用这一块,添加前和添加后都需要相关逻辑来判断某个位置的数据是否已经存在
goTemplate(index1, index2, itemNext) {
    if (!this.userId) {
    this.$set(this.firstItem[1], 'nextArr', [])
    }
    this.getTemplate(itemNext.text)
    if (index1 === 1) return
    let isLive = this.firstItem[1]?.nextArr?.find(item => item.text === itemNext.text)
    let firstItemLength = this.firstItem[1]?.nextArr?.length
    if (firstItemLength === 6 && !isLive) {
    this.firstItem[1]?.nextArr?.splice(5, 1)
    } 
    let secondItemLength = this.firstItem[1]?.nextArr?.length
    let isLiveSecond = this.firstItem[1]?.nextArr?.find(item => item.text === itemNext.text)
    if ((index1 === 0 || index1 > 1) && !isLiveSecond && secondItemLength < 6) {
    this.firstItem[1]?.nextArr.unshift(itemNext)
    } 
    setProjectHistoryPlus(this.firstItem[1]?.nextArr)
},
  1. 全局字体的设置

全局的样式一般会放在静态资源当中,如global.css 然后通过import导入到main.js中,这样样式全局就可以使用了,尤其是字体文件
之前样式放置在APP.vue当中,这样只有部分相关的样式能使用,生成的文本内容就不能使用

  1. 埋点的实现

可以在前端中定义一个自定义指令然后进行相关操作,
在点击按钮处使用自定义指令,每次点击以后都会向后端发送相关请求
后端的接口调用可以通过axios来进行实现操作,通过来直接调用后端的接口 书写接口的时候还需要相关的参数

  1. Vue.directive()的使用

是Vue.js提供的全局指令注册方法,用于创建自定义指令
指令是一种特殊的Vue.js特性,允许你在DOM元素上添加特定的行为和功能

1、导入Vue和创建的指令
import Vue from 'vue';

// 可以自定义指令的名称,例如'custom-directive'
// 可以根据实际需要取一个更具有描述性的名字
const customDirective = {
  // 指令的生命周期钩子函数和配置
  // ...
};
2、定义指令的生命周期钩子函数和配置
- 通过 bind、inserted、update、componentUpdated 和 unbind 等生命周期钩子函数,你可以在指令被绑定、插入到 DOM、更新和解绑时执行相应的逻辑。
const customDirective = {
  bind(el, binding, vnode) {
    // 当指令第一次绑定到元素时调用
    // 可以执行一些初始设置
  },
  inserted(el, binding, vnode) {
    // 当元素被插入到父元素时调用
    // 可以执行一些 DOM 操作
  },
  update(el, binding, vnode, oldVnode) {
    // 当元素的绑定值更新时调用
    // 可以对绑定值进行响应式处理
  },
  componentUpdated(el, binding, vnode, oldVnode) {
    // 当元素和其子组件的绑定值更新时调用
    // 可以进行更深层次的更新操作
  },
  unbind(el, binding, vnode) {
    // 当指令从元素上解绑时调用
    // 可以进行一些清理操作
  },
};
3、注册自定义指令
在 Vue 实例初始化之前,使用 Vue.directive() 方法来注册自定义指令。这样,你的指令就可以在整个应用中使用。
4、 在模版中使用自定义指令
你可以在 Vue 的模板中使用自定义指令 v-custom-directive。
<template>
  <div>
    <!-- 使用自定义指令 -->
    <p v-custom-directive>这是一个自定义指令示例</p>
  </div>
</template>
5、 总结
- 自定义指令可以用于在元素上添加特定的行为,操作DOM、实现自定义的事件处理逻辑等
6、自定义指令的示例
Vue.directive('buried', {
    bind: (el, binding) => {
        const { value } = binding
        el.addEventListener('click', async () => {
            if (getUser().id) {
                // console.log('value', value, typeof value);
                const loginValue = value + 500
                await submitPoint(loginValue)
            } else {
                await submitPoint(value)
            }
        });
    }
})
7、 !!! 非常需要注意的一点是:
编写好自定义指令以后,需要将其导入到师main.js中进行全局引入操作 import '@/directives/buried'
  1. css中如何让文本左对齐; 使用text-align属性,将其值设置为left即可
  2. 使用Vue创建表格
1、使用Vue框架来创建表格的时候,可以将相关数据放置在data中, 通过遍历将数据全部进行展示
2、创建表格的样式
table
tr
th
td
3、数据的书写;
data: {
    headers: ['Header 1', 'Header 2', 'Header 3', 'Header 4', 'Header 5'],
    data: [
        ['Row 1, Cell 1', 'Row 1, Cell 2', 'Row 1, Cell 3', 'Row 1, Cell 4', 'Row 1, Cell 5'],
        ['Row 2, Cell 1', 'Row 2, Cell 2', 'Row 2, Cell 3', 'Row 2, Cell 4', 'Row 2, Cell 5'],
        // Add rows 3 to 12 (similar to the row above)
        // ...
    ]
},
4、template的书写,通过v-for来遍历数据
<table>
    <tr>
        <th v-for="header in headers" :key="header">{{ header }}</th>
        </tr>
        <tr v-for="(row, index) in data" :key="index" :class="getRowClass(index)">
        <td v-for="(cell, cellIndex) in row" :key="cellIndex">{{ cell }}</td>
    </tr>
</table>
5、样式的书写,尤其注意隔行换色
 table {
    border-collapse: collapse;
    width: 100%;
}

th, td {
    border: 1px solid #ccc;
    padding: 8px;
    text-align: center;
}

th {
    background-color: blue;
    color: white;
}

tr:nth-child(even) {
    background-color: #f2f2f2;
}
6、 注意点
- border-collapse: collapse; 是CSS中用于表格的属性,用于控制表格边框的合并方式。
	- collapse是默认值,表示表格边框会合并在一起,相邻的单元格之间的边框会合并为一个单一的边框,没有间隙。这样使得整个表格看起来更加紧凑和一致。
- tr:nth-child(even) 是CSS中的选择器,它表示选中表格中的偶数行(即行号为偶数的行)。
	- 其中 :nth-child(even)是一个伪类选择器表示选中父元素中的偶数位置的子元素
  1. flex布局可以让块级元素水平排列;
  2. 优化代码,避免多层循环出来
- 可以将一些主要信息保存在一些数据结构中,比如多层次对象,把相关的id和title联系起来,构成Map结构。
- Map结构: 键值对的形式
const templatesMap = new Map();
    this.navs.forEach(nav => {
        nav.templates?.forEach(template => {
        templatesMap.set(template.id, template.title);
    });
});
- 而在进行循环遍历操作的时候就可以直接用到上述的结构元素
this.lickTempData?.forEach(item => {
    if (templatesMap.has(item.tempId)) {
    this.firstItem.forEach(iNext => {
        iNext.nextArr.forEach((oNext) => {
        const exists = this.firstItem[0].nextArr.some((item) => item.text === oNext.text);
        if (oNext.text === templatesMap.get(item.tempId) && !exists) {
            this.firstItem[0].nextArr.push(oNext);
            this.firstItem[0].nextArr.forEach(nextItem => {
            Vue.set(nextItem, 'isCollect', true);
            });
        }
        });
    });
    }
})

实习相关内容

  1. 实习历程地址
  2. 项目上线地址
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值