# hm95_vue_basic **Repository Path**: errlei/hm95_vue_basic ## Basic Information - **Project Name**: hm95_vue_basic - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-11-02 - **Last Updated**: 2023-11-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 1. vue脚手架开发项目的步骤 ``` 1. npm i @vue/cli -g 全局安装这个工具,一个电脑只需要安装一次 检查这个工具有没有安装成功,在黑窗口里面,(黑窗口不要用powershell)输入 vue --version 有版本号就表示成功了 2. 借助于这个工具,安装一个项目,安装的项目里面有很多文件夹和文件,这个是开发大型项目必备的,也是我们以后去工作里面需要的内容 vue create heima95 就会冲网上下载一个项目下来,自动帮我们安装node_modules文件夹 (进入以后有一个交互页面,选择 带有vue2的 直接回车) 3. 启动项目 进入项目,打开终端,执行 npm run serve 运行起来以后,需要安装一个插件 vetur。 让我在开发vue项目的时候有代码提示和高亮 ``` ## 2. vue启动项目的流程 ``` 1. npm run serve ----- 这个命令自己去 package.json 文件的 script的属性里面去看 2. 先找到这个项目的 main.js 入口文件, 入口文件里面 引入了整个页面的App.vue 3. 在main.js有一个 $mount('#app') 这句话,那就是将整个vue项目, 插入或者挂载到 index.html里面 以后我们开发这种vue项目,只会写各种 xxx.vue 这种文件, 整个项目里面 就一个 html文件,就是index.html ``` ## 3. 组件化开发 什么是组件? 就是页面上一个个比较小的ui单元, 有自己的独立的js html css。 整个大页面就是由各种小组成,在vue里面我们一个 xxx.vue 文件 就是一个组件 我们的 App.vue是最大的根组件,所有的小组件 都会挂载到根组件上面去,最后根组件放到入口文件 main.js里面去,最后插入到index.html 我们就可以看到完整的页面 ## 4. 组件开发的一些技巧 组件在开发的时候,一般有三个步骤 1. 组件的导入 import xxxx from 'xxxx.vue' 2. 组件的导入 在 components: { 组件名称: 组件的值xxxx } 3. 组件的使用 在页面中 通过 `` > 组件的一些注意事项 1. 组件的名称,需要写多个单词,有语义化,如果单词只有一个, eslint 这个工具 会自动检查你组件名称有没有写好,如果不是多个单词就就报错 1. 如果组件名称改完以后以后,(至少有两个大写单词就可以了), 改完以后如果还报错,那就 ctrl + c 关闭之前由 npm run serve 开启的进程,在重新开启一遍 2. 我们引入组件的时候,组件的名称不要写 和默认的html的标签名称一样。 我们的组件不能写 p div body。 header article 这些都是 html5 自带的标签 https://www.runoob.com/html/html5-new-element.html ## 5. 组件的导入方式 **普通导入和全局导入** 全局导入,需要在main.js里面使用 `Vue.component('组件名称', 导入的组件对象)`, 在任何组件里面使用 `<'组件名称' />` ## 6. 组件里面为什么要添加scoped 很多组件里面的样式文件,默认是针对所有文件。如果想当前的组件的样式 只在当前组件里面生效,只需要给当前组件的style 添加一个 scoped属性即可 原理:给组件加了scoped以后, vue的底层就会给 vue组件在 渲染到页面的时候,给它的dom结构添加一个 data-v-xxx字符串 ,在渲染样式的时候,给这个组件里面所有的样式都添加一个属性选择器,入如果写的样式是 .top 那么最后浏览器渲染出来就是 .top[data-v-sdsdf1234234] 这样一来,这个样式就只针对于当前组件有效 > 那如果我们又想添加一些全局样式?怎么办? 如果想要些全局样式,就不是在 xxx.vue组件里面写,而是在全局 写一个style,里面写css。在那里面去写 ## 7. data为什么必须是一个函数? 在组件化开发的方式里面:如果组件的data使用是普通对象,那么组件在 **复用**的时候,数据就会互相影响。因为对象的地址储存在栈里面,值的引用储存咋堆里面。如果组件复用,那么用对象的方式,修改一个组件的数据,就会影响所有其他组件的数据吗,因为是同一个地址。 相反如果我们使用一个函数,那么每次使用一次组件,data函数就会重新执行一遍,函数返回了一个新对象,就是一个**新地址**。这样组件如果重复使用多次,就会生成多个地址,互不影响 ## 8. 父子怎么通信? 父组件通过props向子组件传递一些数据 子组件通过 this.$emit 抛出一个事件,父组件监听子组件的事件,在回调函数的形参里面有子组件传出来的数据 pros + $emit 父组件的数据只能父组件自己改, 其他组件只能通知父组件去改。 这个过程 叫单向数据流,是vue为了保证数据安全设置的规则。 如果子组件向修改父组件的数据,只能通过 $emit 去通知别人去修改 ## 9. props的校验规则以及一些写法 1. props在工作里面,一般要写带有校验的形式,不能直接写数组 1. 常见的类型有 Number String Boolean Array Object Function 等 2. 校验的时候有required 表示这个属性是否必填 3. 校验的时候有default 表示这个属性是否写默认值。 如果普通数据类型,默认值就是 0 '' 类似这种直接写。 如果是复杂数据类型,比如对象或者数组,默认值就要用 函数 返回一个 对象或者数组的形式,就是要有新地址 4. 如果校验除了类型以外,还需要有自定义校验,就需要通过 validator属性去写。 在函数里面 通过 return true/false 是否显示报错的文字 ``` props: ['w'] props: { w: Number } props: { w: { type: Number, // required: true // 这句话表示这个属性在组件里面必选传递进来,不然就报错 default: 0, // 如果组件有个属性,使用者忘记了传参数,我们就给这个组件一个默认值 // 如果出了基本的类型校验以外,那就需要使用官网的另一属性 validator validator(val){ if(val < 0 || val > 100) { throw new Error('我们的属性w传数字范围只能是0-100') } return true } } } ``` ## 10. 多准备几个项目模板 去我的仓库里面https://gitee.com/errlei/hm95_vue_basic直接使用 1. `git clone https://gitee.com/errlei/hm95_vue_basic` 去公司里面也是这一步操作 2. `npm i 或者 yarn` 安装所有的依赖包,就是安装 node_modules文件夹,如果安装失败了,那么就检查自己电脑的`.npmrc .yarnrc` 有没有配置 **淘宝镜像** 3. `查看package.json 文件里面的 script位置`,执行`npm run serve/dev/build` 就会自动开启一个服务器 ## 11. 事件总线 一般是针对于兄弟组件之间的通信 事件总线的代码是固定的 ``` import Vue from 'vue' const eventbus = new Vue() export default eventbus 导出一个vue的实例对象 ``` **怎么用?** vue的对象实例提供了四个方法 `$emit $on $once $off` 通知,监听,监听一次,移除事件 问你:什么是事件总线? 就是new 一个vue的实例对象。然后导出去,也有另外一个名称,叫事件总线。它上面提供了四个方法 分别是`$emit $on $once $off` 通知,监听,监听一次,移除事件 ## 12. 依赖注入 针对与 父子孙孙孙,无限的后代传值 具体的代码写法,就是父组件 提供数据provide 孙组件 注入数据 inject ``` provide(){ return { num1: this.num } } 孙组件 inject:['num1'] ``` + 如果注入的是普通数据类型,那么就不是响应式的 + 如果注入的是复杂数据类型,那么数据就是响应式的 ## 13. v-model的原理 v-model是vue的一个语法糖而已,含义是双向数据绑定 他的底层代码就是 通过 绑定 value属性 + 监听 input事件 从而实现的双向数据绑定 vue也是一个MVVM的框架,model 由vm调度者 到view 通过 value属性。就是怎么样将数据绑定到页面上去 当我们在页面输入框输入数据的时候,view层 由vm调度者 到 model 通过监听 input事件,将数据传给 js里面。实现了双向数据绑定 ``` 等价于 这个模板template里面 有个默认的变量 $event,表示当前事件的事件对象 ``` ## 14.v-model在自定义组件上面使用 ``` 用在普通的元素上面,表示双向数据绑定, MVVM v-model绑定到自定义组件上面 先了解v-model的语法糖, value属性 + input事件 了解了额v-model的底层代码以后,我们在 实现父子通信的时候, 就可以简写语法,只需要规范好 属性名叫value, 事件名称叫input 就可以简写 以后凡是涉及到表单类型的组件封装,现象的能不能简写 v-model ``` ## 15. sync语法 前面学过的v-model有缺陷, 一个组件上面只能使用一次v-model ``` 等价于 ``` > 问题: 什么是sync? sync 和v-model 都是针对于 父子传值的简化写法。 v-model是默认的value属性 + input事件,一个组件上面只能写一个v-model。 sync语法就是 例如 A.sync 属性就是 A, 事件名称就是 update:A; 一个组件里面可以传递多个sync ## 16. ref vue不推荐我们直接操作 原生的dom元素,如果要操作,需要使用vue专属的语法 vue里面操作dom的语法 ``` 1. 在template的模板里面,需要获取的dom上面 写ref然后写一个字符串
2. 在script里面通过this.$refs.myRef去访问 ``` ## 17. 异步更新$nextTick 页面dom更新是一个异步操作,代码写法 ``` this.$nextTick(() => { // 等dom更新完毕以后,在执行获取dom的操作才会成功   document.querySelector('.ipt') }) ``` ``` 等价写法,定时器, $nextTick底层原理也有setTimeout的代码 setTimeout(() => { // 也是等dom更新完了以后,在执行 console.log(document.querySelector('.ipt')); }, 0); ``` ## 18-自定义指令 可以全局注册也可以局部注册 ``` Vue.directive('focus', { inserted(el) { el.focus() } }) 局部: directives: { color: { // 指令的钩子函数,都有4个参数,我们常用的就2个, 第一个是当前dom元素,第二个是指令传递的值 inserted(el, binding) { console.log(el, binding); el.style.color = binding.value }, update(el, binding) { console.log('指令更新'); el.style.color = binding.value } } } ``` https://v2.cn.vuejs.org/v2/guide/custom-directive.html **指令的生命周期(钩子函数)** 有5个,常用的及时 inserted, 当前被绑定的元素,插入到父元素里面去, 就会自动执行 **钩子函数的参数 有个4个** 常用的参数是前两个。一般叫 el binding el表示被绑定的 dom元素 binding,表示指令传递的值 ## 19. 插槽 默认插槽,具名插槽,作用域插槽 在两个标签中间的内容就是插槽。 父组件向子组件传递了html的结构,就是插槽 ``` 父组件: 中间写内容 MyDialog子组件里面 必须给外面传进来的 html留一个放东西 ``` ``` 如果要自定义的结构有点多,那么就需要借助于具名插槽 父组件 在子组件里面给他留位置 ``` ``` 作用域插槽: 如果父组件的 插槽 想要访问子组件数据 MyTable子组件里面 这句话表示 子组件向外面的插槽传递了3个数据,都放在一个对象里面 上面的abc这个变量,就是一个对象,里面有3个属性,分别是 index count msg ``` ## 20. 路由 1. 路由激活的时候,自动添加一个类名 `router-link-active` 可以修改,但是一般不改 2. 路由传参(2种方式) 1. query传参: ``` 在路由链接上写 朋友 在当前页面的created钩子函数里面,通过$route去访问 this.$route.query this.$route.query.key/type ``` 2. 动态路由params传参: ``` 先要在路由规则表路面配置动态路由 { path: '/friend/:id', component: FriendDetail} 然后在路由跳转的router-link标签上面写 第一个朋友 最后在当前页面通过 $route去访问 this.$route.params this.$route.params.id ``` ## 21. 路由的两种跳转方式 **声明式 + 编程式** ``` 声明式导航---就是标签的形式 访问音乐界面 编程式导航---就是在js里面通过函数的方式去跳转 this.$router.push('/music?a=1&b=2') ``` ## 22. keep-alive 它是一个vue的内置组件,有缓存组件的作用 缓存组件以后,当前组件的创建的4个声明周期函数,就不会在执行,只会初始的时候执行一次 keep-alive组件上面 常见的有三个属性 include 表示哪些组件需要缓存 exclude 表示哪些组件不需要缓存 max表示组件最大缓存的个数 组件如果被缓存,就会多两个生命周期函数 激活 activated 未激活 deactivated ## 23. vuex 开发项目 vue2版本 ---> vuerouter 3.x + vuex 3.x 开发新项目vue3版本 ---> vuerouter 4.x + vuex 4.x vuex 一个**全局状态管理工具**, **全局的数据仓库**, 所有的数据都从这里面取,想要修改,就调用vuex里面的函数 vuex我用过5个属性: state + getters +mutations + actions +modules **state** 在vuex里面定义的全局数据, 在组件里面 通过 this.$store.state.xxxx访问。 有简写的方式,就是通过辅助函数mapState,将state数据转换为计算属性去访问,简化代码 **mutations** 唯一修改state状态值的地方 在组件里面使用 this.$store.commit('函数名称',参数) 使用辅助函数 ...mapMutations(['函数名称']) **actions** 可以放异步代码的地方,这里面想要修改state的值,也不能直接修改,只能通过context.commit 提交一个mutations去修改 在组件里面 通过 this.$store.dispatch('action名称', 参数) 派发/分发 **getters** 从state状态里面派生出来的一些数据,类似于计算属性 在组件里面访问 this.$store.getters.名称 辅助函数...mapGetters(['getters名称'])