1.vue基础

VUE调试工具

vue调试工具步骤:   
	1.远程克隆仓库
  2.安装依赖包
  3.构建
  4.打开谷歌页面
  5.选中开发者模式
  6.加载已解压的扩展,选择shells/chrome

1.组件间数据及交互

数据交互原则: 单向数据流
父组件的数据传递给子组件, 只要父组件的数据变化了,自动重新向下流动, 进而子组件会进行更新数据
所以父组件的数据应该交给父组件修改
数据来源
			data: 自己的数据可以随便更改
			props: 传进来的数据不允许更改, 或者不建议更改 : 防止多个子组件进行数据交错
父传子传递复杂数据类型的说明

修改简单数据类型会报错

修改复杂数据类型,修改地址报错, 如果不改地址,修改对象的属性,不会报错,但是不符合单项数据流

通过elementui 数字输入框只能输入整数_webpack

如果是简单数据类型,  子组件修改了,vue能检测到
  如果是复杂数据类型, 子组件修改父组件出过来的值,不会报错 ,

解决办法 : 表单双向数据绑定

解决办法一 :

            不能用v-model进行与数据绑定 
            用 : checked = 'item.flag' 进行数据绑定  
            通过事件对象$event 事件对象 进行传递, 同时在函数中   function (e){e.target.checked}
            同伙

解决办法二  : 
						将父组件接收过来的数据通过json.parse(json.stringify(arr))转成一个新的数组或者对象
1.父传子

组件内部通过props接收传递过来的值

Vue.component('el-header', {
   props: ['title'],  
   template: '<div>{{title}}</div>'

父组件通过属性将值传递给子组件

<el-header title='来自父组件中的数据'></el-header>  //传递静态数值,一般不用 
<el-header :title='title'></el-header>            //传递变量 动态绑定属性值
1.可以进行传递多个值.
2.如果么有进行传值, 而子组件使用这个数值, 会出现undefined

命名规则

在prop中使用驼峰形式,在模板中需要使用短横线形式 , 字符串形式的模板没有限制,可以使用个驼峰形式

传值规则: 不加 : 传递的是string类型数据, 加冒号是正常数据

如果传递number数据类型, 传递的都是字符串
	:title='12'  //number   	区分类型
	title='12'    //string    不区分类型

注意: 父子组件传值, 数据是异步请求, 有可能数据渲染时, 报错 v-if=isReady

原因:   异步请求时, 数据还没有获取到, 但是此处已经渲染到节点了
	解决方案:   在父组件需要传递数据的节点加上   v-if=isReady (isReady)默认为false, 异步请求获取数据后,isready赋值为true
2.子传父:

子组件向父组件传递的值不是双向绑定的

目的:通过子组件触发事件影响父组件中的数据 或者父组件传递过来的数据,比如通过子组件中的按钮点击放大父组件整个盒子的背景色

  • 父组件监听子组件事件
    本质是监听子组件触发的事件, 同时父组件根据这个事件进行触发相应的函数,这样避免了子组件直接操作父组件传递的数据
尽管数据vue允许子组件去修改父组件数据, 但是在业务中,子组件应该尽量避免依赖父组件中的数据, 更不应该去主动修改他的数据, 以为这样使得父子组件紧耦合, 只看父组件, 很难理解父组件的状态, 因为他可能被任意组件修改,   
理想情况:     
			只有组件自己能修改他的状态, 父子组件最好还是通过props 和$emit来进行通讯

$emit(自定义事件名, 值) 子组件想父组件传递值 ,//好像只能传递一个值, 如果想要传递多个值, 可以用数组或则对象的方式进行传递 ,事件名全部小写

this.$$emit(事件名, 参数1, 参数2,参数3……) //函数里面写

$event 接收子组件传递的值

模板中传值  : 

子组件设置 @click='$emit(enlarge-text')
页面中设置 <son-slot @enlarge='change'>
父组件定义change函数 

方法值设置$emit
子组件通过自定义事件进行传值        
<button v-on:click="$emit('enlarge-text', 0.1)">  //这是直接写在模板里面
  Enlarge text    
</button>
父组件通过设置$event接收参数
页面中设置 <son-slot @enlarge='change($event)'>   //通过在事件里面写$event进行值的获取   方法里面注意后面的$event不写
函数种设置 change:function(value1, value2, value3 , value4....){} value就是$event的形参
案例   : 父组件定义这个事件的时候, 可以是函数方法  changeFont   也可以是  data中的数据  fontSize
      <!-- <el-header :msg="msg" @enlarge="changeFont"></el-header> -->    方法都是用v-on 或者是  @ 
      <el-header :msg="msg" v-on:enlarge="fontSize += $event"></el-header>
3.非父子
  • 单独的事件中心管理组件间的通信
单独的创建一个vue事件对象
var   evetnhub = new Vue()    
 触发事件  进行参数传递   methods              
evetnhub.$emit('子组件事件名称', 传参1)  //触发兄第组件事件 ,向事件中心传递信息 
监听事件与销毁事件   事件的监听写在mounted函数里面  
evetnhtb.$on('子组件事件名称', (接收参数1)=> {})  //监听事件事件中心中的变化 执行相关函数, this指向当前vue实例 本子组件
event.$off('add-todo')

事件注册点击相关

点击子组件click  触发senddata函数,  函数里面有emit,触发emit的change-state事件,  同时页面父元素上有change-state事件  该事件的执行函数为  fn1
3.案例 :todos
单项数据流  
删除功能  :     
								父组件根据id值进行删除list数据 ,父组件注册事件接收参数
增加功能  :   用v-model进行双向数据绑定, 注册键盘回车事件  
修改状态  :   v-model双向数据绑定,但是并没有遵循单项数据流

数据持久化 : 如果是axios版本发送ajax不需要进行数据持久化

watch : {
		list: {
				deep: true;
				handler(newValue) {
						localStroage.setItem('todos-data' , json.stringify((newvalue))) 
				}
		}

数据获取 :

created: function (){}

2.组件插槽

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YEBtxbke-1604141484224)(C:\Users\22359\AppData\Roaming\Typora\typora-user-images\1600936632623.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lGVbZMqV-1604141484231)(C:\Users\22359\AppData\Roaming\Typora\typora-user-images\image-20200925175147455.png)]

1.语法:

在子组件标签之间传递内容

里面的请输入正确的手机号码 , 请输入用户名, 不是写死的, 用插槽

为甚要用插槽 :

通过父传子, 自定义型较差, 通过插槽可以进行自由定制内容

作用:

用于实现组件的内容分发 ,自由定制任意结构, 用slot标签进行接收内容

  • 在vue中,在子组件标签里面填写内容是不显示的, 这样需要用到插槽的方式进行传递
  • slot标签确定传递内容的位置
  • 如果slot中有默认内容,会被默认显示,如果父组件没有传递内容,slot中的内容会被覆盖
<el-header>错误提示</el-header>
//   组件插槽
      Vue.component('el-header', {    
        template: `
            <div> 
                <strong> error:</strong>
                <slot></slot>
            </div>
            `,
      })

2.具名插槽: 有名字的插槽

  • template: 向子组件中传递多个标签, template并不会渲染到页面
  • 一般插槽 里面可以包裹多个标签
  • 插槽默认 {{msg}} 直接值slot使用
    注意:
    vue-2.6版本中, v-slot指令取代了slot 与slot-scope,但是v-slot使用时, 需要在template标签上使用,不能在普通标签上使用
    template通过v-slot指令绑定插槽, v-slot:header, header不加引号 不是等于号进行绑定数据
    slot=‘header’ 是通过属性进行绑定 . 所以是=号, 不是 :
向子组件传递自定义标签名的插槽 ,通过name属性绑定,即将标签换成插槽传递给子组件

标签中传递的内容根据传递的slot属性进行传递, 子组件根据name进行匹配,没有匹配到的根据作为默认插槽使用
只能标注一个标签, 如果需要多个标签的话, 用template包裹,template并不会渲染到页面
<el-header>
        <p>默认信息</p>
        <p slot="header">这是title信息</p>
        <p slot="footer">这是footer信息</p>
</el-header>
 template: `      
            <div> 
                <slot> </slot>//默认插槽
               <header>
                    <slot name='header'> </slot>
                </header>
                 <footer>
                    <slot name='footer'> </slot>
                </footer>
            </div>
            `,
      })

3.作用域插槽

如果子组件中有数据, 希望在父模板分发内容是使用, 可以使用作用域插槽

给插槽添加属性的方式, 给父模板传值,

  • 给插槽,添加属性的方式传值
  • 所有添加的属性 , 都会被收集到一个对象中, {yes:’确认’., no; ‘ 取消’, moneny : 100}
  • 在template中, 通过=即可接受子组件传递过来的数据,这样可以操作子组件传递过来的数据
  • 如果子组件向模板传递过来的数据命名和vue实例中的数据名相同, 在模板中, 会使用子组件的数据
  • 模板的范围属于谁,使用的就是谁的变量 比如子组件里面的模板, 其实模板使用的变量是不是组件的, 而是vue实例所以插槽里面如果有点击事件的方法写在vue实例里面, 而不是写在子组件里面作用域插槽使用场景
    表格模板中,delelte操作时不固定的, 也可能是add,所以需要设置template进行自定义,防止把子组件写死
    但是点击delete或者add时,需要发送id,进行ajax操作,所以子组件向插槽传值
    注意:template 插槽的名称不要重复,否则下面的插槽会覆盖上面的插槽,
    插槽里面如果需要操作数据,添加方法,需要将插槽写在tmeplate所在位置, 而不是插入的子组件mo模板的范围属于谁,用的就是谁的变量
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <style>
      td,
      th {
        padding: 2px 5px;
      }
    </style>
  </head>
  <body>
    <div id="box">
      <el-student :list="students">
        <!-- 设置组件插槽 -->
        <template v-slot:caozuo="obj">
          <a href="#" v-on:click="sendid(obj.id)">{{obj.title}} {{obj.id}}</a>
        </template>
      </el-student>
    </div>
    <!-- 创建模板 -->

    <script src="../vue.js"></script>
    <script>
      Vue.component('el-student', {
        props: ['list'],
        template: `
                <table>
            <tr>
                <th>序号</th>
                <th>姓名</th>
                <th>班级</th>
                <th>年龄</th>
                <th>性别</th>
                <th>操作</th>
            </tr>
            <tbody>
                <tr v-for='item in list'>
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
                <td>{{item.class}}</td>
                <td>{{item.age}}</td>
                <td>{{item.gender}}</td>
                <td><slot :id='item.id' :title='"删除"'  name='caozuo'></slot></td>
                </tr>
            </tbody>
            </table>
        `,
        methods: {
          sendid(id) {
            console.log(id)
          },
        },
      })

      //   作用域插槽 : 如果插槽需要使用组件中的数据, 比如子组件中的id值 或者数据
      const vm = new Vue({
        el: '#box',
        data: {
          students: [
            {
              id: 1,
              name: '张给',
              class: '高中',
              age: 18,
              gender: '男',
            },
            {
              id: 2,
              name: '李四',
              class: '高中',
              age: 18,
              gender: '男',
            },
            {
              id: 3,
              name: '张三',
              class: '高中',
              age: 18,
              gender: '男',
            },
            {
              id: 4,
              name: '张静',
              class: '初中',
              age: 18,
              gender: '女',
            },
          ],
        },
        methods: {
          sendid(id) {
            console.log(id)
          },
        },
      })
    </script>
  </body>
</html>
父组件传递的插槽 通过=号解释   
 <template v-slot:bottom="obj">
          <!-- {{ obj }} -->
          <button>{{ obj.yes }}</button>
          <button>{{ obj.no }}</button>
          <div>{{ obj.friend }}</div>
        </template>
子组件模板传递的数据   直接在slot进行传递数据  
  <slot :yes="yes" :no="no" money="100" name="bottom" :friend="friend"></slot>

4.插槽规则

插槽的几种形式 v-slot只能在template中写

<div slot="error">            有标签的插槽
    <template v-slot:'error'>      模板插槽
    <template v-slot:'error'='obj'> 传递数据的插槽
    <div>

单页应用程序spa

多页应用程序

每次点击都会重新刷新页面

单页应用程序

优点 :   
				每次只需要获取必要的数据,减少请求体积, 减轻服务器压力
	缺点:  开发成本高(需要学习路由)
				不利于seo搜索引擎优化----用户搜索时搜索不到: 解决方案: 利用node中 ssr进行服务端渲染

3.路由

  • 路由基本概念:
路由是浏览器url中的哈希值,(#hash)  与展示视图内容(组件)之间的对应规则
简单来说: 路由就是一套映射规则(一对一的对应规则),有开发人员制定规则
当rul中的哈希值(#hash)值发生改变之后, 路由会根据制定好的规则,展示对应的视图内容(组件)
  • 为什么要学习路由
渐进式--->vue-vue-router(管理组件之间的跳转)
在webapp中,经常会出现通过一个页面来展示和管理整个应用的功能
spa往往是功能复杂的应用, 为零有效管理所有视图内容, 前段路由出现

vue中的路由 : 是hash和component的对应关系,一个哈希值对应一个组件

点击链接, url是上的hash会发生变化, 在在检测到变化的时候切换对应的组件,就实现了路由的使用,同时由于通过hash的方式是不跳转页面的,所以实现了spa单页面应用程序
1.哈希值 hash
浏览器地址栏#后面的名字   文件本页面通过href跳转, 只是点击之后修改地址栏的哈希值
vue-router就是利用这个原理 :       
				利用锚点跳转. 通过改变地址栏的hash值, 将来可以切换对应的组件
2.router语法

步骤1: 设置基本项 router:router

下载 npm i vue-router
引包 (先引入vue包到html页面)  以为router依赖于vue  
使用,创建路由实例 cosnt router new VueRouter() 
将当前的路由实例挂载到vue实例中, 建立联系    router:router

步骤3: 配置路由规则

定义路由组件

cosnt router = new VueRouter({   router代表路由实例对象
		routes: [{path:'', compontent:''},{}]   
//routes代表路由规则(路线集合) 一条路由规则就是一个对象  格式 : {path:路径,compontent:组件的配置对象}
     可以将compontent在外面定义
})

步骤3: 添加路由填充位router-view,对应的组件展示位置

路由填充位(也叫做路由占位符)
将来通过路由规则匹配到的组件, 将会被渲染到router-view所在的位置
<router-view></router-view>

步骤4: 添加路由链接router-link ,点击切换组件

<router-link>是vue中提供的标签, 默认会被渲染成a标签
to属性默认会被渲染成href属性 
to属性的值默认会被渲染成#开头的hash地址  ,用于指定要跳转的路由地址
注意: 后面的本来是<a href='#top'>  但是为了区分 vue设置成了#/需要添加/  ,同时又将#自动取消了 ,在url中vue自动添加了#/
<router-link to='/uesr'>user</router-link>
<router-link to='/register'> 点击更换组件b<router-link>
3.router-link使用
  • router-link-exact-active精确匹配 类名
  • router-link-ative模糊匹配 类名
两种方式在匹配时会加上相应的类名      
router-link-exact-active  to里面配置的hash值路径必须完全一样才会加上类,给这个a标签加上这个类名
router-link-active  to里面配置的hash值路径开头只要包含就能进行匹配
 <router-link to="/Detail/fsadfsad">detail</router-link>
导航链接 :    实际渲染出来就是a标签,
					2.必须配置to属性, 用于指定跳转的路由
4.相关设置
1.重定向:
path:'/', 如果用户访问的/ 进行重定向,,重新设置路由路径,匹配组件  
{path:'/', redirect:'/default'}
第二种方式 通过component设置重定向
{path:'/', component:User}
2.设置自定义类名 ,默认高亮的类名是可以定制的
当点击的router-link中设置的to路径与地址栏上完全一样是,就会添加这个类名
linkActiveClass:'current'         模糊匹配
linkExactActiveClass:'current'

to里面写完整路径

5.嵌套路由

注意: 子路由进行嵌套时设置重定向, 尽量使用redirect设置路径, 如果设置component 添加类名的时候添加不上

重定向进行设置显示分类页
子分类下的/需要取消
如果path中相对路径,会自动将父路由的path拼接在前面
children: []
6.编程式导航

核心: 通过js的方式进行跳转路由,叫做编程式导航,比如点击button进行跳转

之前学的是用a标签进行跳转路由,写href进行跳转,声明式导航

this.$router.push(‘hash地址’)

this.$router.go(1) 在浏览历史中前进, -1为在浏览历史中后退

注意:前进只有在后退之后才能进行前进,因为是历史记录中的后退

例如  : 通过js跳转    如localcation.href = 'www.baidu.com'
vue中通过js的方式进行跳转, 但是vue中不是local,因为local跳转的是整个页面
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T4CYLdle-1604141484237)(C:\Users\22359\AppData\Roaming\Typora\typora-user-images\image-20200927195856593.png)]
  • 语法 :
this.$router.push(路由路径)
  例如" 
  <button @click='jump'>
  		methods: {
        
        	jump() {
            this.$router.push('/user')
            或者
            router.push('/user')
          }
      }

this.$router 完全等价于 router 就是唯一的router实例

7.动态路由匹配
渲染商品1  渲染商品2 ......  多个额商品只需要准备一个模板, 里面的参数变化就行了,比如点击京东手机列表, 显示的都是同一个格式的页面thi
this.$route 当前路由的相关信息, 比如参数, 路径
如果要获取当前的路由的相关信息,用this.$route
用watch进行监视this.$route  每次只要路由变化了, 地址也变了, 就会有一个新的this.$route(不用深度监视)
但是created函数里面都是同一个route参数, 以为组件是同一个组件,点击切换的时候组件并没有被销毁或重建, created仅仅执行了一次, 所以都是同一个值
watch: {
		$route(newvalue){   }   
		}
<ul>
        <li><router-link to="/shop/1">商品1</router-link></li>
        <li><router-link to="/shop/2">商品2</router-link></li>
        <li><router-link to="/shop/3">商品3</router-link></li>
        <li><router-link to="/shop/4">商品4</router-link></li>
        <li><router-link to="/shop/5">商品5</router-link></li>
      </ul>        
      <router-view></router-view>
 routes: [{ path: '/shop/:id', component: Item }],

动态路由参数获取 this.$route watch监视路由变化

只要想拿当前的路由的路径或者参数,就找this.elementui 数字输入框只能输入整数_webpack_02

route 一条路由规则 , 一个对象{path:'/user',compontent:User}
this.$route当前的路由的相关信息,比如路径,参数
fullpath :  url地址栏中数据的完整信息,包含查询参数
path    #后面的不包含含查询参数的路径 
query  解析后得到的查询参数对象  ?username=张丹娜&pass=123解析成对象之后的    
params  可以获取动态路由参数     /shop/1后面的1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-djbFVtoN-1604141484245)(C:\Users\22359\AppData\Roaming\Typora\typora-user-images\image-20200927174343805.png)]

8.router区分
this.$router指向router实例
app.$router指向router实例
router.push  指向router实例
问题: 后面的开发环境当中,每一个模块都是独立的,存放到单独的文件中,   互相之间不能访问到router变量.vue中把router实例给每创建出来的组件绑定了$router,这样都能进行访问到router
routes: 配置路由规则时写的, 多个路由规则, routes:[]
route 	一条路由规则
9.命名路由

为了方便表示路由的路径, 可以给路由规则起一个别名, 即为‘命名路由’

属性绑定 通过: to

命名路由的方式直接在router-link中进行传递参数
路由规则设置: 
	routes: [{ path: '/shop/:id', name: 'mingming', component: Item }],
 声明式导航    路由链接设置   注意写 冒号 
<router-link :to='{name:'mingming', params:{id:123}}'>
 编程是导航链接设置
router.push({name:'mingming',params:{id:124}})

自定指令

案例:autofocus在vue中不能使用, 因为部分浏览器不兼容, vue屏蔽了

应用场景: 通用的dom操作时,使用自定义指令

前置知识: 
			created: 一般发送初始化渲染数据
			mounted:可以进行dom操作
	如果进行的通用的dom操作, 并且可能多个页面都需要获取焦点, 推荐将focus封装到自定义指令中

1.分类 :

全局指令

局部指令

全局指令语法
定义指令: 
	Vue.directive(指令名,配置对象)
   对象里面可以配置5个钩子函数
函数一:   inserted(el)   
    指令所在的元素被插入到页面中时,这个函数触发
    el代表被插入的元素
		
使用指令:
 v-指令名
局部指令语法
directives: {
	focus: {
				inserted(el) {}
	 }
}

2.五个钩子函数

注意 自定义指令的钩子里面没有vue实例, this指向window

  • bind(){} 指令和所在的元素,绑定时触发,在bind一般进行初始化,bind一般只触发一次,在这里获取不到el元素内容,无法插入元素
  • inserted(){} 绑定后,元素被插入页面中时触发,*可以进行操作dom.dom已经渲染上去了
  • update(){} 当指令的值更新时触发,速度比componentUpdated快一点
如v-demo='info'
  • componentUpdated(){} 指令所在的元素(组件),dom更新完成后触发
  • unbind 实例销毁时触发, vm.$destory
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VNDZ1wM0-1604141484249)(C:\Users\22359\AppData\Roaming\Typora\typora-user-images\image-20200928153744619.png)]

参数

el 指令所在的元素
v-on:click.stop.prevent='fn1'
binding--------------------------------------- 包含了设置的参数
name指令名   	on
value指令值   fn1
modifiers  修饰符对象形式    指令显示loading加载中效果  stop prevent

自定义指令的简写

条件: bind和update逻辑elementui 数字输入框只能输入整数_vue.js_03完全一致

要求比较严格
普通写法
bind(el, binding) {}
uprate(el,binding){}
如果bind 和 update逻辑完全一致, 可以简写
Vue.directive('指令名', 处理函数) 表示同时处理bind, update

2. vue-动画

1.转场动画

概念 :  中间过渡动画,控制元素侠士隐藏,配合v-if使用
当通过if进隐藏显示的时候,平常写的时候没有这个设置

v-enter在元素即将进入页面的时候添加

v-enter-to 在元素完全进入页面时添加这个类

v-enter-active在元素进入页面的动画过程中

v-leave在元素即将离开页面时

v-leave-to在元素完全离开页面

v-leave-active在元素离开页面的过程中

2.translation可以设置name属性

transsition name='fade' 当前给元素添加的动画的类名前缀就变成
fade-enter
fade-enter-to
......

3.animation动画

步骤:  使用transition将需要使用动画的元素包裹
			包裹了元素,元素就有了动态切换的6个类  v-enter  v-enter-to  v-enter-active  v-leave v-leave-to  v-leave-active
animation from to
举例
		@keyframes bounce {
			0% {
			transform : scale(0)
			}
			50%{
			transform:scale(3)
			100%{
			transform:scale(1)
			}
		}
		animation form to 在动画中, 设置好了,动画的开始, 动画结束的模式
		
		.v-enter-acitve {
				animation
		}

3.vuex

1.概念

  • 集中式状态管理工具,用于组件之间传递数据
  • 将组件之间共享的数据放在vuex中管理
  • vuex中的数据是响应式的, 如果a组件的数据修改

vuex的特点

集中式,响应式

vuex 和localstroage区别

  1. vuex是响应式的,localstroage不是,vuex中的数据,组件a中的数据会自动改变, 而localstorage需要自己主动获取, 才能达到更新

如何正确使用vuex

  1. 如果项目小,不需要使用vuex,用了可能会增加项目难度
  2. 只有在写项目的时候, 发现组件通讯多, 组件之间的关系复杂,项目已经无法继续开发, 此时使用vuex
  3. 如果是组件共享的数据才放在vuex里面

2.vuex基本使用

  1. 引入vuex.js文件
  2. 通过vuex创建一个仓库 const store = new VuexStore()
  3. 挂载到app根实例上,通过this.$store.state…获取值,设置值

3.vuex中的严格模式

const store= new Vuex.store({
   strict:true,
    state:{}
}
  1. 添加严格模式后不能在mutation外面修改state中的数据
addData () {
   this.$store.dispatch('addAsync', { tagName: this.tagName })
  }
========================================
  // 异步添加 
  // context ≈ store
  addAsync(context, payload){
    //1. 异步
    setTimeout(()=>{
      // 2. 提交
      context.commit('add',payload)
    },1000)
  }
}
## 4.actions

vuex 可以正确的监听 mutations ,但是 异步的除外,-- mutations 里面不能放异步的,否则监听有问题

mutations : 同步 + 修改数据

actions : 异步 + 提交同步

## 5.mapState(数据映射)

**mapState映射  vuex中的数据放在组件中的computed中**

1. 引入vuex里面的辅助函数  `import {mapState}from 'vuex'`
2. 组件的computed中

```js
computed: {
	...mapState(['list'])  //获取list数据
}

3.如果组件中的data中的数据和mapState中冲突了,可以改名,对象形式

computed : {
	...mapState: ({"item" : list})
}

6.mapGetters(映射数据)

  • import {mapGetters} from ‘vuex’
  • computed
computed: {
	...mapGetters(['isShow'])
	}
  • 自定义名称,如果发生和组件中的数据重名
computed : {
	...mapGetters({
		isShow1: isShow
	})
}

7.mapMutations(映射方法)

放在方法里面

  • import {mapMutations} from ‘vuex’
  • methods
methods: {
	...mapMutations(['delData'])
}
  • 调用 this.delData ,del中的名字和methods中重名.会发生最大调用栈溢出
  • 重新起名
methods: {
	...mapMutations:({'d':delData})
}

8.mapActions(映射异步)

  • import {mapActions} from’vuex’
  • methods
methods: {
	...mapActions(['addAsync'])
	...mapActions({'add1': addAsync})
}

9.指定页面跳转

需求:

  • 进入home页面,就把home页面缓存
  • 离开home到tablist页面里面,把home页面从缓存中移除
  • 移入其他页面,再次进入home页面, 再次把home页面缓存

步骤

  • 定义include数据
<keep-alive :include="cacheList">
  • 将cacheList:[‘home’, ‘search’]放在vuex中,使用vue管理cachaList
  • 配置vuex, 安装vuex, 创建store文件夹,index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
	state: {
		cacheList:['search']
	}
	mutations: {
	//增加: 比如home添加到cachelist 
		cache(state,payload){
if(state.cacheList.includes('payloa.name')) {
			state.cacheList.push(payload.name)
			}
		}
	//删除 : 删除home
		uncache(state,payload){
		if(state.cacheList.includes(payload.name) {
        	    state.cache=state.cacheList.filter(v=>!=payload.name)
        	}
		}
	}
})
  • app.vue设置keepalive标签
<keep-alive :include="cacheList">
import {mapState} form 'vuex'
computed:{
    ...mapState(['chaList'])
}
  • 在home中的beforeRouterLeave设置beforeRouterEnter和beforeRouterLeave守卫, 已进入home页面就将home缓存起来
beforeRouterEnter(from. to , next){
		//在此中获取不到vue实例对象 this.$store.commit('cache'),,因为此时组件还没有创             建,守卫执行前. 组件实例没有创建 
		//解决办法: import sotre from 'store/index.js
		store.commit("cache")
		next()
}
  • beforeRouterEnter中判断from判断上一个路由信息对象是否talist, 如果是, 调用vuex中的删除home函数
离开home页面去tablist页面不要缓存,从home从cache中移除,移除之后会再次创建,不能只在进入时判断,因为离开时会销毁'
if(to.path==='tablist'){
   this.$store.commit('uncache')
}
  • beforeRouterLeave中添加home

4.项目上线打包

1.打包步骤

  • yarn build 只需要给dist文件交给后台
  • 在dist文件夹里面开启一个本地服务器,模拟一下:live-server

2.打包前的准备工作

  • 关闭console.log,将log方法重写,在main.js的顶端进行重写
console.log=()=>{} //设置什么都不写,
  • 更换基准地址开发阶段
1.开发阶段基准地址 : http://localhost:3000
2.发布阶段基准地址:  http://baidu.com.
process.env  获取环境参数
axios.defaults.baseURL=process.env.NODE_ENV==='development' ? '                http://localhost:3000' : ' http://baidu.com'
  • 注意:每次修改了代码,开发环境刷新一下进行,发布环境需要重新打一个包
  • 如果ebusy忙碌中. 说明正在使用, 找到终端, 把live-server断开,两次ctrl c

3.工程化webpack设置

1.模块化规范

1.传统开发模式的主要问题

  • 命名冲突: 多个js文件之间如果存在重名变量,会发生变量覆盖
  • 文件依赖: js文件之间无法实现相互引用解决方法: 模块化 2.模块化概念
    解决方法: 模块化

2.模块化概念

模块化就是单独把一个功能封装到一个模块(文件)中,模块之间相互隔离, 但是可以通过一个特定的接口将内部成员,也可以依赖别的模块
模块化开发的好处: 方便代码的重用,从而提升开发效率,并且方便后期的维护

3.服务器端模块化规范

浏览器端
amd 模块化   require.js
cmd模块化  Sea.js

4.服务器端模块化规范

commonJS   只用于服务器端
 1. 模块分为 单文件模块, 与包,
 2.模块成员导出:   module.exports和exports
 模块成员导入 : require('模块标识符')

5.通用模块化规范

每一个js文件都是一个独立的模块
导入模块成员使用import关键字
暴露模块成员使用export关键字

6.导入导出

导出方式一 : export {  name, falg}
导出方式二 : export var num= 7899;
import  { name, flag}  from './mmm.js'
非自定义导出方式, 导入时候需要与导出的名称完全一样
导出函数 : export function fn1 () {return num2 +num1)
自定义导出  default在同一个模块里面只能只一个, 不能是多个 
export default num
import  自定义名称  from './mmm.js'

2.webpack用法

1.webpack概念

基于js的静态模块打包器
  • 打包的说明
打包目的: 将多个文件压缩成一个文件, 减少请求的次数,减轻服务器压力
  • webpack能做什么
  1. 语法转换:
1. 将less/sass/stylus 转换成css
2. typescript(ts)转换成js   $ts中有非常严格的类型检测$
3. es6转换成es5/es3  比如imrt
  1. 将多个文件合并成一个文件
如果项目要上线, 一定要先打包压缩,后上线
  1. 可以起一个开发时的服务器,可以做到保存时自动刷新浏览器
自动开启浏览器
自动监视文件费
自动刷新浏览器
  • 在webpack中,一切的静态资源都是模块
静态资源: 不需要后端额外处理的文件内容
.php .asp .jsp 这些不能浏览器直接解析的,需要服务器进行解析的
静态资源:  html ,js css  png jpg jpeg...
只要是模块,可以当成模块导入,使用模块语法  require('./a.js')  require('./1.png')  require('./1.css')

2.yarn的使用

下载地址 https://yarn.bootcss.com/docs/install/#windows-stable

yarn与npm类似, 都是包管理工具, 可以下载包, 管理包
1.初始化    yarn init  / yarn init -y  新建一个package.json文件
2.装包     yarn add 包名   
3.删除包   yarn  remove 包名           
4.安装依赖 yarn  yarn install                  
5.全局安装 (了解, 一般不用, 全局安装一般用npm) 
		yarn global add json-server
		yarn global remove json-server

3.打包步骤

以后使用对着官网面对着博客配文件,

步骤:

创建目录
src 存放源代码 , 里面有main.js, 整个打包的入口文件,姜凯从这个文件开始打包
dist: 存放打包后的文件 
yarn 安装依赖
  1. yarn init
  2. yarn add webpack webpack-cli -D
--save  简写 -S  默认值, 装包时,不写默认添加    npm i vue -S 等于npm i 
将包记录成项目依赖      
--save-dev 简写- D
		npm i webpack -D 等于  npm i webpack --save-dev    
将包记录成开发依赖,这个包只是开发过程中依赖的包
  1. 在package,json中配置scripts
seripts: {
	"build": "webpack ./src/main.js -o ./dist/bundle.js"    
}
  1. 运行npm run build打包或者 yarn build
    指定开发模式 –module=develoment
打包会跳出警告  :   mode有两种模式,默认生产模式
production 生产模式(生产环境)----将来上线的环境(压缩版本)
development 开发模式----现在开发过程的环境(未压缩,便于查看源码)
设置指定模式  ==将其打包成开发版本
seripts: {
	"build": "webpack ./src/main.js -o ./dist/bundle.js --module=development"    
}
  1. 后面文件在src里面的main.js或者index.js入口文件中引入
    npm中- - save 和- -save-dev的区别
1--save简写成-S , 将安装包作为项目的依赖,(目前为默认值)
早起npm安装包的时候, 必须加上--save才会添加到package.json项目依赖中去
2. --save-dev 简写-D : 将安装包作为开发阶段的依赖
#tips
		dependences: 项目依赖, 项目上线也要用的
		devDependencles:开发依赖, 只有在开发中使用, 上线是不要用的
注意点:  yarn add jquery -D;  yarn只认识-D

3package.json配置scrips命令,配置自己的命令

第一步  配置命令
"scripts": {
        命令名字:命令内容,
        "pp": "yarn add vue"
   }
第二部  执行命令
	npm run 命令名字
  npm run pp  /yarn pp
第三部    ==特殊的命令:  如果npm要执行的是start或者是stop,可以省略run==
"scripts": {
        命令名字:命令内容,
        "start": "yarn add vue"
   }
第四部	运行命令  npm start /  yarn start 
				工作中都是配置start 运行.app.js脚本文件

webpack配置到配置文件中

  • 配置配置文件
  • 设置自动dev插件
  • 自动复制html文件插件

生产环境: 上线的环境,代码需要压缩合并处理的production

开发环境:还在开发中, 代码一般不压缩的(可以查看源代码)development

  • 1.创建一个新目录: dist src/main.js
配置命令到配置文件中:直接在pack中配置不了太多 代码乱太难看==
同时在webpack目录里面创建webpack.config.js文件

2.初始化 : yarn init -y

3.安装依赖包

yarn add webpack webpack-cli -D

4.配置scripts

--config webpack.config.js这个配置文件名为默认值,不加默认也会找这个文件

scripts: {"build":"webpack --config webpack.config.js"}
		scripts: {"build":"webpack"}  默认会找当前目录下的webpack.config.js   js文件

5.提供webpack.config.js文件位置在webpack文件夹下,和package.json同级

参考文档: https://webpack.docschina.org/concepts/#入口-entry-

解释:

这个文件是webpack的配置文件, 将来webpack打包时,会加载当前文件
	按照配置的规则进行打包
	webpack ./src/main.js -o ./dist/bundle.js  --mode=development设置开发环境

webpack.config.js代码设置步骤

const webpack = require('webpack')
	
	// webpack是基于modejs的工具
	// 打包设置的绝对路径
	const path = require('path')
	module.exports = {
	  // 设置模块导出
	  // 1.配置打包入口文件, 从哪个文件开始打包----------------
	  entry: './src/main.js',
	  // 2.配置打包出口,打包到哪里去,文档中规定,出口文件必须使用绝对路径,需要引入path文件,设置绝对路径-----
	  output: {
	    //   路径
	    path: path.join(__dirname, './dist'),
	    //   打包后生成自定义的文件名   js前民不能写/   写了就变成了相对路径
	    filename: 'js/bundle.js',
	  },
	  //3.模式设置:确定是开发者模式或者生产环境 -上线环境
	  mode: 'development',
	}

备注: 假定在main.js中导入一个aa.js,多个文件需要打包,webpack会打包成一个文件,可以节约请求的次数,仅仅会请求一次

require('./aa.js')
	log("这是main模块")

基于webpack实现隔行变色

  • 新建public/index.html文件编写代码
  • public文件夹
文件夹中放置index.html文件, 将来indehtml中不会戏太多内容, 都是通过vue组件来渲染
  1. index.html内部引入dist/bundle.js文件夹.书写代码特别注意:如果不使用插件的话, 多余的文件任然在dist文件中
<div id="app">
	  <!-- ul>li{我是第$个li}*10 -->
	  <ul>
	    <li>我是第1个li</li>
	    <li>我是第2个li</li>
	    <li>我是第3个li</li>
	    <li>我是第4个li</li>
	    <li>我是第5个li</li>
	    <li>我是第6个li</li>
	    <li>我是第7个li</li>
	    <li>我是第8个li</li>
	    <li>我是第9个li</li>
	  </ul>
	</div>
	
	<script src="../dist/bundle.js"></script>
	</body>
	</html>
  1. 在src文件的main.js文件中引入jquery文件,使用jquey隔行变色
    main.js中书写代码
安装jquery :  yarn add jquery  yarn add moment
	
	// 需求: 通过jquery实现隔行变色
	const $ = require('jquery')
	const moment = require('moment')
	
	$(function() {
	  $('#app li:nth-child(odd)').css('color', 'red')
	  $('#app li:nth-child(even)').css('color', 'green')
	
	  $('#app li:last-child').text(moment().format('YYYY年MM月DD日'))
	})

.自动生成html -html-webpack-plugin插件

目前我们都是在index.html中国手动移入打包后的资源,这种引入方式是有缺点的比如:

文件依赖问题: 假如webpack配置中的输出文件名修改了, 需要及时在index.html同步修改

1.下载

yarn add html-webpack-plugin -D

2.在webpack.config.js文件中引入这个模块

// 插件: 自动生成 html 的插件, 可以自动引入打包后的文件
	const HtmlWebpackPlugin = require('html-webpack-plugin')
	//写在module.exports里面
	  plugins: [new HtmlWebpackPlugin({ template: './public/index.html'})],
3.配置好了之后`public目录的index.html文件`就不需要打包后的js或者css文件了,会被插件生成html引入

4.设置之后,插件会将设置的index.html复制一份到dist文件夹下,并且将设置的之前根据文件打包入口文件出口文件路径filename的路径,

根据设置的路径,将其bundle.js引入dist文件夹下html中

webpack-dev-server插件自动刷新

1.下载

yarn add webpack-dev-server -D

2.配置scripts,在webpack.json文件中设置

scripts: {
		"build":"webpack --config webpack.config.js"//这个文件是之前配置的,用于设置配置文件的,创建一个config文件
		"dev": "webpack-dev-server --config webpack.config.js"
}

3.在webpack.config.js的module中配置

配置开发服务器的配置
devServer: {
		port:3000,//端口号
		open: true,//自动打开浏览器
}

webpack中处理css文件

webpack-loaders的配置

webpack默认只认识js文件和json文件, 但是webpack可以使用loader

所以webpack如果想要处理其他文件类型,记得要先配置对应的loader

需求 :去掉小圆点,新建css目录

1.安装依赖,同时在main.js文件中引入index.css文件

sytl-loader和css-loader都安装到设置开发环境里面
yarn add style-loader css-loader -D

2.配置

module: {
    rules: [
      {
        //   正则表达式, 用于匹配所有的文件
        test: /\.css$/,
        //   先用scc-loader让webpack能够识别css文件内容
        // 在用style-loader将样式,以动态创建style的方式添加到页面中
        use: ['style-loader', 'css-loader'],
      },
    ],
  },

webpack分离css文件

上面的操作 是css和js文件混杂在一起了, 将css放到了style标签中,和html一起加载了一个文件请求次数是少了

但是如果css文件太大的话,也不是太好, 需要将css分离出来

  1. 有一个插件,mini-css-extract-plugin , 这个插件支持webpack4.x
  2. 还有一个插件extract-text-webpack-plugin 这个插件对webpack3.x的版本支持, 被webpack4.x废弃了
    1.安装依赖包
yarn add mini-css-extract-plugin -D

2.在webpack.config.js文件中,引入这个模块

引入分离css文件的模块
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

3.配置loaders 覆盖原来的**一定要覆盖原来的css解析设置**

// 模块加载 
module: {
  // loader的规则
  rules: [
    // 配置 css 文件的解析
    {
      test: /\.css$/,
      use: [ // 根据官方文档写的,注意'css-loader'的书写位置
        {
          loader: MiniCssExtractPlugin.loader,
          options: {
            publicPath:'../',  //路径相当于将dist 中main.js文件的上一级 创建一个文件
          },
        },
        'css-loader'
      ]
    },
  ],
}

4.配置插件

// 定义打包好的文件的存放路径和文件名
new MiniCssExtractPlugin({ 
   filename:'css/index.css'  //相当于之前publicpath中写的../上一级路径创建一个css文件目录下/index.css
})

5.设置完成之后就变成了link引入的模式

webpack less文件处理

1.下载依赖包

注意: 解析less文件需要识别 less 语法, 所以除了 less-loader 需要额外下载 less

less-loader: 将less转换成 css

yarn add less  less-loader  -D

2.配置

// 配置 less 文件的解析
{
  test: /\.less$/,
  use: [
    // 分离出 css 内容
    {
      loader: MiniCssExtractPlugin.loader,
      options: {
          publicPath:'../',
      },
    }, 
    'css-loader',
    'less-loader' 
  ]
}

webpack中处理图片-url-loader

webapck不识别图片,此时需要转换图片中的loader,来处理图片的问题, 主要用到

url-loader 和file-loader

注意: url-loader中的部分功能要用到file-loader,要下载两个模块

配置图片的加载规则:

``

1.下载两个依赖包

yarn add url-loader file-loader -D

2.配置loader

如果不配置图片, 图片将被处理成base64字符串的格式, 好处: 节约请求的次数,注意:一般推进将小图片转成base64 图片转成base64, 体积会增大30%左右,

所以: 如果是小图片 直接转, 如果是大图片需要单独处理

{
        test: /\.(png|jpg|gif|jpeg)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              //超过8k 单独引入,不到8k, 转base64
              limit: 8192,   // 8*1024b  即为8kb
            },
          },
        ],
      },

配置图片输出的打包目录

默认是直接输出到了 dist 根目录, 可以通过 options 进行配置

{
  test: /\.(png|jpg|gif)$/,
  use: [
    {
      loader: 'url-loader',
      options: {
        // 超过 8k 就不转 base64, 小于 8k 才转字符串
        limit: 8 * 1024,
        // 配置输出的文件名
        name: '[name].[ext]',
        // 配置静态资源的引用路径
        publicPath: "../images/",
        // 配置输出的文件目录
        outputPath: "images/"
      }
    }
  ]
}

webpack配置字体图标

webpack 配置字体图标 - url-loader

在main.js中设置加载require加载字体图标的css文件

require('./icon.css')
// 处理字体图标的解析
{
  test: /\.(eot|svg|ttf|woff|woff2)$/,
  use: [
    {
      loader: 'url-loader',
      options: {
        limit: 8 * 1024,
        // 配置输出的文件名
        name: '[name].[ext]',
        // 配置静态资源的引用路径
        publicPath: "../fonts/",
        // 配置输出的文件目录
        outputPath: "fonts/"
      }
    }
  ]
}

webpack清除dist目录的插件

使用clean-webpack-plugin插件,在每次打包前清除dist文件夹
安装依赖包 
yarn add  clean-webpack-plugin -D

在webpack.config.js文件中运行

// 其他代码

// 导入清除插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    // 其他配置

    plugins: [
      // ....
      // 调用清除打包目录插件
      new CleanWebpackPlugin()
    ]
};

webpack开发服务器处理语法兼容

webpack使用babel处理高版本的js语法

babel的介绍: 用于处理高版本js语法的兼容性

yarn add -D babel-loader @babel/core @babel/preset-env

配置规则

module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env']
        }
      }
    },
  ]
}

webpack.config.js总体设置参考

// 这个文件是webpack的配置文件, 将来webpack打包时, 会加载当前文件
// 按照配置的规则进行打包
// webpack ./src/main.js -o ./dist/bundle.js --mode=development

// 错误:
// 1. 漏装包, 装错包(包名写错)
// 2. 配置单词, 逗号

	// 插件: 自动生成 html 的插件, 可以自动引入打包后的文件
	const HtmlWebpackPlugin = require('html-webpack-plugin')

// 引入分离 css 文件的 模块
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
                
// 导入清除插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
					
const path = require('path')

// webpack是一个基于nodejs的打包工具
module.exports = {
  // 1. 配置打包入口文件, 从哪个文件开始打包
  entry: './src/main.js',
  // 2. 配置打包出口, 打包到哪里去
  output: {
    // 打包到哪个目录
    path: path.join(__dirname, './dist'),
    // 打包后生成的文件名
    filename: 'js/bundle.js'
  },
  // 3. 配置打包的模式 production development
  mode: 'development',

  // 4. 模块的加载配置
  module: {
    // 规则
    rules: [
      // 1. 配置css加载的规则
      {
        // 匹配所有 .css 后缀的文件, 进行处理  i: ignore 忽略
        test: /\.css$/i,
        // 配置加载的loader
        // 处理的顺序, 从后往前
        // 1. css-loader 先处理, 让webpack具备了解析css, 读取css文件的能力
        // 2. style-loader 后处理, 将读取得到的css, 以 js 动态创建style标签的方式, 作用于页面
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../'
            }
          },
          'css-loader'
        ]
      },

      // 2. 配置less加载的规则
      {
        // 匹配 .less 后缀的文件
        test: /\.less$/i,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../'
            }
          },
          'css-loader',
          'less-loader'
        ]
      },

      // 3. 配置图片加载的规则
      // 默认不配置, 图片将被处理的base64字符串的格式, 好处: 节约请求的次数
      // 注意: 一般推荐将小图片转base64, 节约请求, 如果是大图片, 请单独请求处理
      // 图片 转 base64 => 会比原有的体积 增大 30% 左右
      // 所以:
      // 1. 如果是小图片, 转base64
      // 2. 如果是大图片, 单独引入处理
      {
        test: /\.(png|jpg|gif|jpeg)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              // 超过 8k, 单独引入, 不到 8k, 转base64
              limit: 8 * 1024,
              // 配置输出的文件名
              name: '[name].[ext]',
              // 配置静态资源的引用路径
              // 例如: 从index.css 出发, 找图片, ../images/xx.gif
              publicPath: "../images/",
              // 配置输出的文件目录
              outputPath: "images/"
            }
          }
        ]
      },

      // 4. 配置对于字体图标的加载
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[name].[ext]',
              publicPath: "../fonts/",
              outputPath: "fonts/"
            }
          }
        ]
      },

      // 5. 配置babel, 将新版本的es6语法 => es5/es3 浏览器兼容的语法
      // 正则中的 ?, 表示可以出现 0 次 或 1次
      // .js
      {
        test: /\.js$/,
        // exclude 排除, 设置排除项, 哪些目录是不需要进行解析编译的
        exclude: /(node_modules)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  },

  // 5. 配置插件
  plugins: [
    new HtmlWebpackPlugin({ template: './public/index.html' }),
    // 定义打包好的文件的存放路径和文件名
    new MiniCssExtractPlugin({
      filename: 'css/index.css'
    }),        
    // 调用清除打包目录插件
    new CleanWebpackPlugin()
  ],
								
  // 6. 配置开发服务器的配置
  devServer: {
    open: true, // 自动打开
    port: 3000  // 端口号
  }
}

// 脚手架 => vue-cli 自动生成 webpack 配置
// publicPath 决定了静态资源文件的加载路径, 不要乱改

总体设置路线

  • 创建dist src less css js 文件
  • 清除dist目录的插件,每次重新生成会删除之前的插件
  • webpack-dev-server插件自动刷新设置
  • 自动生成html -html-webpack-plugin插件
  • 设置css插件 设置css插件分离设置
  • 设置less插件
  • 设置fonts插件 注意 fonts需要在main.js文件中引入 font.的css文件
  • 设置es6语法兼容babel插件

生产环境开发环境分离

生产环境与开发环境刚好相反, 开发环境在本地运行, 生产环境在服务器端,给用户使用的代码, 因此两者的构建目标很大, 比如打包后的文件要在生产环境中要尽可能的小, 逻辑代码分离吗优化静态资源,(压缩图片等)

因此,开发环境和生产环境不能共用一份webpack配置文件, 需要分别指定

但是两个环境还是有很多配置是可以共用的吗比如entry output module等, 因此 可以把公共部分的配置抽离出来, 放到一个单独文件,然后进行合并, 可以使用webpack-merge工具进行合并

config文件夹: 放当文件 config只能使用旧版本语法 src中使用新版本语法,以为有babel

  1. webpack.base.js 这个文件专门用于存放公用的配置
  2. webpack.dev.js专门存放开发环境文件,不压缩的
  3. webpack.pro.js上线打包的文件,

通用里面不用设置mode

dev导入基础配置对象: cosnt base =require(‘./webpck.bbase.js’)

yarn add webpack-merage -D
//使用合并webapck配置的插件
const {merge} = require('wbpack-merage')
//merage(合并对象)

build对应生产环境上线

dev对应开发环境设置

开始拆分webpack.config.js 文件, 拆分以后,这个文件就不要了

新建config文件夹

-webpack-demo
		-config   //存放配置文件的文件夹

			-webpack.base.js //公共配置
			-webpack.dev.js//开发环境的配置
			-webpack.pro.js.//开发环境的配置
   -//其他文件

4.es6 模块化

前言

require module.exports ===>es5

import export (浏览器和node都不支持),新语法都被webpack解析才能运行

解决: 在之前的js中一直没有模块系统的, 前辈们提出了commonjs规范,amd规范

amd淘汰cmd淘汰

标准化模块化语法=>es6模块化语法通用的模块化解决方案=>import导入=>export导出

一个模块就是一个独立的文件,该文件内部的所有变量, 外部无法获取,如果希望外部能够读物模块内部的某个变量, 就必须使用export关键字输出该变量,

es6新增了两个命令: export import , export命令用于规定模块的对外接口, import命令用于输入其他模块提供的功能

1模块导入导出

导出的数据只能获取不能设置导入后相当于const 变量名, 不能重复设置

1.精确导出:

导出多个值一一对应

可以根据需求进行导入导出,按需导入,导出时导出的方法使用的当前的模块的变量或者数据,是否能够获取到

export funcion (){}
export cosnt num =11
export cosnt arr =[]
export obj js
export {num1 , name1 ,age} 
import{num1 ,name1 , age}  from ‘./a.js’
  • export{name1 , age1 , obj , arr } ,一般放在最后
  • export tellStory
  • import {name1, age1 , obj , arr } from ‘./a.js’

2. 默认导出:

导出一个值

export default指定默认输出, 只能导出一个值, import无需知道变量名,就可以直接使用

export default 值 (将这个值,作为了当前模块的导出)
export default num 
import 自定义变量名 from  './a.js'

3.import ‘./index.js’导出

4.兼容和说明

只能在src文件里面写es6语法

5.webpack处理Vue组件

1.vue单文件组件的介绍

single-file components (单文件组件) 文件扩展名为.vue文件,需要安装vetur插件, 以前顶一个组件非常麻烦, 需要写template模板, 在里面写模板字符串, 但是有了单文件组件就不需要再写

单文件组件文档

优势:

  • 完成语法高亮
  • comoonjs模块
  • 组件作用域的css

新建项目只需要复制之前的config package.json

新建pupblic文件目录,创建index.html文件

yarn安装依赖包

yarn dev启动

yarn add -D vue-loader vue-template-compiler
// webpack.base.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  module: {
    rules: [
      // ... 其它规则
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  },
  plugins: [
    // 请确保引入这个插件!
    new VueLoaderPlugin()
  ]
}

inex.html设置

<div id='app'>
  	不写任何结构代码
</div>
  不需要引入任何的包,将来html-webpack-plugin会自动打包
  要引入任何的包,将来html-webpack-plugin会自动打包

在src中创建App.vue文件

src 中componets组件是通用的组件 ,可以全局注册 也可以局部注册 使用时注册当成标签使用

src中views是页面性质的组件,使用与跳转切换的, 需要配合路由使用的,一般都是大写

src中router放置路由规则

单文件组件

组件结构写在template麻烦 , 没哟提示, 默认导出方式默认写法忽略了样式
创建vue文件
<template> 
  </template>
<script>
   export default { return {}}
  </script>
  <style>
  </style>

创建views 文件夹, 存放Home.vue组件, 和Login组件 , 创建路由实例

import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'

import Home from './views/Home.vue'
import Login from './views/Login.vue'

Vue.use(VueRouter)  //都要使用

const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/login', component: Login }
  ]
})

new Vue({
  el: '#app',
  // render函数用于渲染一个组件作为根组件(固定写法)
  render (createElement) {
    // 把App组件作为根组件
    return createElement(App)
  },
  router
})

抽取路由代码 :将路由功能从main.js中抽取出来

新建router/index.js文件

// 配置所有的路由的功能
// 模块化环境开发
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../components/Login.vue'
import Home from '../components/Home.vue'
Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { path: '/login', component: Login },
    { path: '/home', component: Home}
  ]
})

export default router

修改main.js文件

import Vue from 'vue'
import App from './App.vue'
import router from './router'

new Vue({
  el: '#app',
  // render函数用于渲染一个组件作为根组件(固定写法)
  render (createElement) {
    // 把App组件作为根组件
    return createElement(App)
  },
  router
})

6.vue-cli脚手架

概念 :命令行界面,俗称脚手架.只需要在命令行输入命令 就可以自动生成配置文件宣贯设置,

作用: 快速生成开发环境,以及对应的webpack配置,开箱即用

查看公司使用npm还是yarn,否则公司下载资源有冲突

1.步骤

1.全局安装脚手架

npm install -g @vue/cli
# OR
yarn global add @vue/cli
查看版本
vue --version 或者  vue -v

问题1:查看是否添加淘宝镜像

npm get registry

问题2:安装淘宝镜像

npm config set  https://registry.npm.taobao.org/

注意上面安装的是vuecli3版本, 如果需要按照vuecli2方式初始化项目是不可以的,

问题3

报错 : 无法加载文件  C:\Users\Administrator\AppData\Roaming\npm\vue.ps1,因为在此系统中禁止执行脚本

方法1 : 
- 打开 powerShell 用管理员身份运行 (很重要)
- 输入命令: set-ExecutionPolicy RemoteSigned 
- 输入 A
- 再输入 vue -V (搞定)

方法2 : 找到本地路径删除 ps1文件删除
- C:\Users\xxxxx\AppData\Roaming\npm

2.创建一个项目

命令

vue create  vue-demo
  • 提示1:选择preset
? Please pick a preset: (Use arrow keys)   请选择一个 preset
   default (babel, eslint)     默认设置
>  `Manually select features`    手动设置 ( √ )2

提示2: 选择用户技术栈

空格是切换选中, 回车是完成

? Check the features needed for your project:   勾选你项目中用到的技术
 (*) `Babel`                               `babel es6=>es5`                     
 ( ) TypeScript
 ( ) Progressive Web App (PWA) Support        
 (*) `Router`                              `路由 vue-router` 
 ( ) Vuex
>(*) `CSS Pre-processors`                  `预编译 less`
 ( ) Linter / Formatter
 ( ) Unit Testing
 ( ) E2E Testing
  • 提示3 : 是否使用history模式
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)   ==> `输入 n`
? 是否使用 路由的 `histtory` 模式
 - history模式 => 不带#
 - hash模式    => 带#  ( √ )
  • 提示4 : 预编译
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): (Use arrow keys)   选择一个预编译css的方法
   Sass/SCSS (with dart-sass)
   Sass/SCSS (with node-sass)
>  `Less`   ( √ )            根据你选择的  vue-cli 会下载合适的包和loader
   Stylus
  • 提示5 : 配置文件安置在何处
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
  Babel 和 ESLint 等等 配置文件放在哪里??   
   In dedicated config files    单独一个文件
>  `In package.json`              都放在 package.json  (√)
  • 提示6 : 是否保存你的选择为一个 preset
Save this as a preset for future projects? (y/N)  是否保存你的选择作为一个preset
 1. 输入 n  => 不保存
 2. 输入 y  => 保存预设 并命名
   Save preset as:   xmg
预设保存在本地文件 : C:\Users\xxx用户名\.vuerc
  • 提示7 : 安装成功,运行项目
�🎉  Successfully created project vue-demo.
�👉  Get started with the following commands:

 $ cd vue-demo
 $ npm run serve

2.rem适配

1.安装rem适配插件,以后开发以375为标准

npm i lib-flexible 
作用:根据屏幕添加fontsize

2.main.js引入rem插件

import 'lib-flexible'

3.安装postcss-px2rem

npm i postcss-px2rem
//作用:自动将px转换成rem

4.在vue.config.js中添加rem转换配置文件,配置完成之后重新启动

注意 remUnit

到公司怎么干

1.首先查看公司原型图 ,如果原型图是750,就是75,如果是375就是37.5

2.看到的设计图上的尺寸是多少px,就写多少px,rem会自动适配

//添加配置文件remUnit,如果公司设计稿是375就设置37.5,如果公司设计稿为750,就设置成75, 设计稿的1/10

3.登录功能

1.创建组件,先创建两个组件页面 Login.vue /Register.vue

elementui 数字输入框只能输入整数_javascript_04

页面组件都是通过路由控制显示的

公共组件都是通过全局注册,局部注册控制显示的

import VueRouter from 'vue-router'
Vue.use('VueRouter')
const router =new VueRouter({
		routes:[]})
//导出
export default  router

2.设置路由规则

  • 引入页面login组件
  • 设置router出口—–
  • 配置路由规则,设置重定向redirect

3.封装components组件

  • 头部组件封装HmHeader.vue
  • 全局注册组件使用(main.js)
import Hmheader from '../component/HmHeader.vue'
Vue.component('hm-header', HmHeader)
  • 在login中使用公共组件

在登录页登录

在注册页 注册

在hm-header添加 插槽是父组件向子组件传值

  • 设置样式flex
  • 封装logo组件
  • 处理登录封装同时设置插槽
  • 处理输入框
  • 关于封装组件设置的步骤
创建
注册
使用
细化

4.scoped

作用: 由于是单页面应用, 会出现样式共享,解决组件中样式共享的问题,是当前组件的样式只对当前组件内的标签其效果

操作: 在当前组件里style里面添加scoped 添加之后会在属性样式

给vant 组件的类名设置样式时发现不起作用

原理

添加scoped之后 ,结构会添加data-v-xxx属性
样式通过属性选择器 h1[data-v-xxx]找到匹配的标签添加样式
在组件的根节点上添加 data-v -xxx 而设置的那个类在组件的内部, 没有这个属性,
.div [dta-v-xxx]  {margin:10px}  //设置scoped之后, 样式变成了这种样式

深度作用选择器: 给引入的组件内部设置自定义样式

如果是css : >>>

如果是less sass : /deep/ 或者 ::v-deep .li

ul>>> .li{ margin:0px }

>>> .li

[data-v-xxx] .van-tabs_nav {margin:0px} 先父级属性为data-v-xxx , 再找组件里面的.li

总结: 以后组件中的标签scoped需要添加 ,如果是标签是没有任何影响的, 如果是组件内部设置样式, 需要设置深度样式选择器

5.vant -ui库

所有文档安装步骤进行从官网设置安装

1.安装vant

npm i vant  Z
//在main.js引入vant组件

2.引入vant组件

设置自动按需引入

全局引入 不推荐
按需引入需要添加插件

安装babel插件npm i babel-plugin-import -D

配置插件 在更目录下babel.config.js中添加配置

根目录文件设置之后需要重启

注意数据名称后面添加注释\

触底加载注意事项

  • 获取数据的最小总高度需要大于页面长度
  • finished , pageIndex 第几页,初始化 ,
  • 数据初始化
  • 设置设置下拉刷新时,和切换标签 时需要设置loading =true, 然后再调用获取数据的函数
  • 切换标签式, 如果触底会触发onload事件, immediate-check 只在组件初始化时触发一次,即为点击进行页面
首先设置不触底加载, 但是设置的不触底加载为组件生成的时候不进行触底加载, 
切换标签页后, vant会认为是滚动事件,会自动检测底部距离, 进行触底加载, 如果不需要可以设置成loading=false

4.登录按钮绑定登录事件, 父传子

方法1: 
		父传子注册事件, 同时button组件设置点击事件, this.$emit('click')
方法2:native修饰符  父传子的语法糖
直接在组件上使用@click.native
5.设置点击登录校验,向后台发送数据,进行校验
组件弹窗使用toast组件, 在组件中使用this.$toast('提示内容')
在main.js中使用Toast('提示内容')
登录是否成功以data中的statuscoede为准, 不是status

vant组件中list组件的使用

load-触底触发事件

offset -设置触底的距离,

immediate-check 是否立即检测, 如果初始数据内容不足一个屏幕大小 , 需要设置此参数,进行自动检查, 因为不足屏幕大小, 不能触发页面滚动, 也就不能检查时候触底

v-model=‘loading ’:用于指加载状态, 如果没有此数据, 满足条件后会一直触发loading事件:

如果为true—->正在加载中, 不会触发load事件

如果为false—–>当满足offset条件是会触发load事件

使用; 滚动触发,插件内部会自动修改loading:true, 正在加载数据

加载完成; 设置loading:false,写在ajax中

finished属性, boolean值, 当为true值, 不在进行加载,如果发送的数据长度小于设定的长度, 说明数据已经没了, 不在进行加载数据

finished-text=‘数据加载完毕, 已经没有数据了’

git

1.本地管理

五点半提交代码, 尽早提交代码,以防冲突,新建一个压缩包, 每天的写的代码自己压缩一个文件包, 自己保存下来

git log 查看日志

git init 初始化

git checkout -b 'dev'创建dev分支

git status 查看当前状态

git add . 提交所有文件暂存区

git commit -m 'login页面完成' 提交仓库区

git checkout master 切换到主分支

创建远程仓库 —-注册登录

https和ssh

https每次推送需要输入用户名和密码

ssh不需要

  • 已有仓库
设置一个别名
git remote add origin git@gitee.com:王万琦git
如果忘了切换sssh  一定要检查 git-开头的, 不是https
  • 生成公钥——码云官网=-====>点击生成公钥======>点击公钥管理=====>点击生成公钥===复制命令
-- ssh-keygen -t rsa -C '邮箱名称'
随便随便找个终端; 连续三次回车====> 见到火星文说明生成公钥成功
  • 查看本地公钥和私钥, 只有公钥和私钥同步,才能免密
c\users\default\.ssh----> .ssh
id_rsa:私钥
id_rsa.pub: 公钥
赋值公钥代码, 找到官网, 添加输入密码
  • 推送到远程仓库
//添加一个远程仓库.,并且给他起一个别名 mycangku
git remote add mycangku  git邮箱
//推送远程仓库,推动到mycangku 的主分支 里面去
git pull 远程仓库地址       第一次上班, 下班走之前gitpulllay拉一下          
git push -u mucangku master     //添加-u 以后, 每次只需git push 就行, 相当于设置默认选项
  • 分支操作

git branch查看分支

git branch 'login'创建分支

git checkout 'login' 切换分支

git branch -D 'login' 删除分支

git checkout -b 'login' 创建并切换分支

git checkout master切换到主分支

git merge 'login'将login分支与merge合并

git pull 每次git push 之前先git pull一下

5.axios设置

axios.get(url, config)

config :配置对象

参数对象,比如要删除哪一条id,GET没有数据
params:{id=1}
请求头对象
headers:{token}

axios.post(url, data, config) , post一般是添加/上传,需要有data请求体参数

axios.post(http://localhost:3000/login', {usernmae:""}, {params:{},headers:{}}

axios.put(url,data,config) 修改id 4的整个数据

axios.put(http://localhost:3000/login', {usernmae:""}, {params:{id=4},headers:{}}
axios.put(http://localhost:3000/login', null, {params:{id=4},headers:{}} //null站位

axios.delete(url, config)删除id 4数据

axios.delete(http://localhost:3000/login',  {params:{id=4},headers:{}}

axioas处理

  • 每次都要引入 —挂载原型
  • 每次都要添加基准地址 –全局统一设置
    将axios挂载到Vue原型上,每一个组件vue实例都可以使用了
import axios from 'axios'
Vue.prototype.$axios=axios
//使用的时候  this.$axios
axios.defaults.baseURL = 'http://localhost:3000' 
图片地址更换  $axios,defaults.baseURL + info_user_img

拦截器:处理token

请求拦截器拦截所有axios请求,发送ajax请求

axios.interceports.request.use(config => {
	if(token) {
	config.header
}
	})        //config代表设置axios中的config

,响应拦截器拦截响应-拦截失效的token信息, 比如修改密码

失效时登录无线循环问题

async添加处理

  1. async 必须加到最近的函数
  2. async必须和await成对出现
  3. 通过try{}catch((errror)=>{})进行捕获异常

6.页面跳转传值

1.字符串对象this.$router.push('/login')

2.对象传值

^方法一: 缺点:参数都放在url上面,数据暴露在url地址栏中^

this.$router.push({path:"/login', query:{
            username:this.username,
             password:this.password
  }})

方法二: 命名路由传值 , 如果不在router中设置name , 只写path:‘/login’不会传递

params传值是通过name属性进行查找传递的

路由规则中设置添加name属性
{
    path: '/',
    redirect: '/login',
    meta: { title: '登录页面' },
    name: 'login',
  },
// 跳转传值
that.$router.push({
                  path: '/login',
                  name: 'login',
                  params: {
                    username: that.username,
                    password: that.password
                  },
                })
//接收传值
 created () {
    const { username, password } = this.$route.params
    console.log(this.$route);
    if (username && password) {
      this.username = username
      this.password = password
    }
  },

7.头像图片压缩

一般用object-fit;cover

设置个人头像,用户上传的头像可能不是正常比例的,如果图片本来不是1:1比例的,设置width70,height70px ,会出现变性

object-fit : cover cantin

object-fit:cover等比例缩放,保证短边完整,超出的部分上下对称截掉,保留中间部分

object-fit : contain; 等比例缩放, 保证长边能显示完整,可能部分显示不全,同时居中

8.moment时间过滤器

9.未登录访问页面

跳转之前进行判断token, 如果不是按部就班的点击跳转, 而是修改入口,上述方法就不行

如直接输入url地址

7.Authorization 验证 -token

1.token令牌

2.http请求是无状态的

登录跳转页面之后,后台不知道,因为没有记录

前段浏览器——–>后台服务器

登录成功(用户名,密码)——>加密生成token令牌——>保存到本地localStorage.setItem(‘mytoken’, token)—->解析token进行验证

以后在请求数据的携带token解析进行验证,在get请求中发送用户id , 同时在config对象中传递Authorization设置token

created () {
 
    axios.get('http://localhost:3000/user/:id', {
      headers: {
        Authorization: localStorage.getItem('usertoken')
      }
    })
  }

将获取到的数据进行保存到vue数据中 this.info = res.data

然后在模板中进行渲染,注意设置imgsrc是需要设置本地服务其中的地址,再进行与info中的数据进行拼接

通过设置v-if设置男女性别

8.导航守卫:直接在router.js设置导航守卫

作用:拦截页面之间的跳转

beforeEach 前置钩子, 路由跳转之前触发的钩子

从from跳转到to组件

to代表当前的路由规则

from代表上一个路由规则

next函数被调用之后才能进行下一个生命钩子

next('/login')可以更改跳转的组件,可以在这里面进行判断是否用户是否登录的密码,如果没有登录密码,需要重新回到;login页面
next(false)如果在跳转页面的时候,用户点击了取消,可以进行中断页面跳传操作

meta元数据 , 描述数据的数据

注意 router.beforeEach只有在嵌套子路由中才有效果

router.beforeEach(function (to, from ,next ) {})
next函数内部自动调用next , 如果自己写reouter.beforeEach如果不使用next就是不会进行跳转路由
meta:元数据,在发送的route中设置 是一个对象,
this.$route({
	path:'/login',
	meta:{title:'登录页面'},
	query: {username:"战三"}
})
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import Login from './../views/Login.vue'
import Register from './../views/Register.vue'
const routes = [
  {
    path: '/login',
    component: Login,
    meta: { title: '登录页面' },
  },
  {
    path: '/',
    redirect: '/login',
    meta: { title: '登录页面' },
  },
  {
    path: '/register',
    component: Register,
    meta: { title: '注册页面' },
  },
]

const router = new VueRouter({
  routes,
})
router.beforeEach((to, from, next) => {
  document.title = to.meta.title   //设置浏览器头部显示
  next()  //next()函数如果是自己设置必须执行, 如果不执行不会发生路由跳转
})
export default router

如果不显示,这样写

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VVEgkQ8y-1604141484257)(C:\Users\22359\AppData\Roaming\Typora\typora-user-images\image-20201009232042540.png)]

2.导航守卫补充

  • 后置守卫(钩子) router.afterEach() 跳转之后调用
after函数里面没有next函数
router.afterEach((to, from ) => {
  console.log('aftereach')
})

router.afterEachrouter.beforeEach被称之为全局守卫:

  • 路由独享的守卫

写在一个routes规则里面 next()必须调用才能进入下一个

const router new Vuerouter(  { 
	routes: {
	path:'/login',
	component:Login,
	beforeEnter:(to,from , next) => {
			next() //必须调用
	 }
	}

})
  • 组件内的守卫

写在组件内,详情使用查文档数据

7.keep-alive遇见vue-router

组件内部所有的状态没有保留,如果进行切换,会发生组件初始化

keep-alive是vue内置的一个组件,也可以使被包含的组件保留状态, 或者避免重新渲染

router-view也是一个组件, 如果直接被包在keep-alive里面,所有路径匹配的视图组件都会被缓存

应用场景:嵌套路由

当发生嵌套路由跳转的时候 , 发生调回原来页面的话,可以进行keep-alive回到嵌套路由的某一个路由页面

9.git命令项目

  1. 查看分支 g

10树状结构递归组件

树形结构数据: parent : {parent: {parent:{}}}

递归组件:组件内部使用组件自己

1.组件a里面使用组件b, b组件注册全局/局部/路由控制, ======>显示即可

2.组件a里面的模板里面使用a自己 ======> 添加name =‘aa’

3.注意v-if终止条件,因为递归有可能一直循环下去, 可能造成死循环

11.this.$refs.element

vue中的数据更改是同步的,但是数据渲染dom的过程是异步的,所以获取不到dom最新的元素

改成异步的

12.嵌套对象数据渲染 报错解决方案

detail.user.nickname 报错问题

数据渲染的时候, template模板会先编译一遍detail={} detail.user====> undefined undefined.nickname====>报错

解决方案: 1detail里面添加一个空对象,user:{}

data() {return {detail:{user:{}}}}

解决方案:2 在 {{detail.user.nickname}}<

13.nextTick

定义: 下次dom更新循环结束之后执行延迟回调, 在修改数据之后立即使用这个方法, 获取更新之后的dom

  • 作为一个promise使用
  • async getData() { await this.elementui 数字输入框只能输入整数_前端_05refs.input.color=red}

14.keep-alive

作用: 用于保留组件状态或者避免重新渲染,

  • 通过在组件中添加name属性进行指定需要保留组件状态的组件
  • imclude 字符串或者是正则表达式,只有名称匹配的组件会被缓存\
  • max 最多可以缓存多少组件实例, 超过数量时, 时间最长的未活跃的会被创建
  • <keep-alive include='a,b,c'>
  • 如果需要指定son页面返回时 , father页面不会刷新, 但是从其他页面返回时刷新数据,需要在rotuer给som路由规则设置,通过keepalive为true
  1. 进行传值
{
      path: '/detail/:id',
      component: Detail,
      meta: {
        keepalive: true,
      },
    },

2.在father页面进行判断

// 判断上一次数据路由的
  son -----> from  beforerouteenteer  to------> father
  beforeRouteEnter(to, from, next) {
    if (from.meta.keepalive) {
      console.log('dtail路哟')   //来的路径
      console.log(to)
      to.meta.keepalive = true
      next()
    } else {
      to.meta.keepalive = false   //此时路径
      next()
    }
  },
  1. rotuer-view 出口 中 keepalive通过meta中的keepalive进行判断
<template>
  <!-- 出口 -->
  <div id="app">
    <keep-alive
      ><router-view v-if="$route.meta.keepalive"></router-view
    ></keep-alive>
    <router-view v-if="!$route.meta.keepalive"></router-view>
  </div>
</template>

keep-alive生命周期钩子 毁掉第一个第一个组件是或组件是或组

activated : 被keep-alive缓存的组件激活时调用 , 进入组件

deactivated: 被keep-alive缓存的组件失活时调用, 离开组件

//从本地获取 此处是缓存后切换显示时调用activated
//created====>gettablist 从本地获取, 页面刷新时调用

15.回滚

如果划到底部,点击发表评论后想看到刚发表的内容 (滚动到某个位置)

  • 在 评论列表的上面, 添加一个空盒子 <div ref='box' />
  • 发表评论成功, 跳转到该位置

this.$refs.box.scrollIntoView()

16.搜索页面

如果本地存储获取不到, 会返回null 或者undefined --不确定

如果本地存储设置grandfather----> father------>son 如果father不存在, 并且设置son 会报错

17pc端

pc端后台管理 登录页面

项目创建准备 vue create pc01

2. 官网视频设置 拉取2.x模板(旧版本)

npm install -g @vue/cli-init   //或者vue init
vue init  webapck my-project

3.基于3.x版本的脚手架创建vue项目

1基于交互式命令行的方式创建新版vue项目
vue create my-project  
2基于图形化界面的方式,创建新版vue项目
vue ui   
3基于2.x的旧模板 ,创建旧版vue项目
npm install -g @vue/cli-init
vue init webpack my-project

4.vue脚手架的自定义配置

1.通过package.json配置项目

必须是符合规范合法的json语法,在最底部设置
"vue" :{
  	"devServer": {
      "port":"8000",
        "open": true}
}

2.以上做法不推荐, 单独定义到vue.config.js文件中国进行配置

在项目根目录文件创建vue.config.js

在改文件中农进行相关配置,从而覆盖法默认配值

module.exports = {
  devServer: {
    port: 8888,
    open: true
  }
};

7.element-ui基本使用

vue2.0的桌面组件库:省省略美化样式的时间

1基于命令行方式的手动安装

步骤:

1.安装依赖包 npm i element-ui -S

2.导入Element-UI相关资源

//导入组件库
import ElementUI from 'element-ui';
//导入组件相关样式
import 'element-ui/lib/theme-chalk/index.css
//配置Vue插件
Vue.use(ElementUI)

2.基于图形化界面自动安装

  1. 运行vue ui 命令
  2. 通过vue项目管理器计入具体的项目配置面板
  3. 点击插件 添加插件 进入插件查询面板
  4. 搜索vue-cli-pligin-element并安装
  5. 配置插件, 实现按需导入, 从而减少打包的项目的体积

vue.config.js中关闭语法检测

lintOnSave:false,
   devServer: {
       overlay:{
           warning:false,
           errors:false
       },
       ...
}

前项目技术栈

vue
vue-router
element-ui
axios
echarts

后端技术栈

node.js
express
jwt  //状态保持工具,实现登录记录功能
mysql
sequelize  前后端项目分离模式

8.前段项目

1.项目初始化

  1. 安装vue脚手架
  2. 通过vue脚手架创建项目 vue ui创建项目
  3. 配置vue路由
  4. 配置element-ui 组件库
  5. 配置axios库,安装axios依赖,运行依赖
  6. 初始化git远程仓库
  7. 将本地项目托管到github或者码云中

步骤

###git ee安装公钥

添加公钥成功之后, 在终端输入
ssh -T git@gitee.com
是否添加到可信任列表中
yes

gitee上传绑定邮箱账号

账号 :wangwanqi999
密码 :wangwanqi999

后台环境安装配置

安装mysql数据库
安装node.js环境
配置项目相关信息
启动项目
使用postman测试后台项目接口是否正常

启动数据库 解压apiserver,导入数据

在apiserver目录下运行npm install命令,安装依赖包

上述

模块化语法

1.下载安装配置node.js版本文件

2.下载安装git

git需要path路径,配置密匙

点击右下角图标 —— ctrl shift p 输入git 命令,将选中的分支合并到当前分支

1.vs创建分支

点击创建新的分支, 输入分支名称.点击云图标,上传至git

3.安装插件

vue ——高亮语法

3创建项目

vue ui 创建项目 安装lint 开发依赖

图纸 imooc_xiaomi@163.com

4.安装

5本地存储

cookie , storage 区别

  • 存储大小 : cookie 存储4k(有时候存储大量的报文. 内存不够) , storage 5m
  • 有效期: cookie拥有有效期,过期之后cookie会自动消失, 存储在内存中, storage只存储在浏览器端
  • 路径:cookie有路径限制, storage只 pi: cookie没有特定的api , storage有对应的api
  • cookie会自动发送到服务器端, 用作用户唯一凭证 , storage只存储在域名下

6.接口统一拦截

  • 统一报错
  • 未登录统一拦截 返回login页面
  • 请求值, 返回值统一处理
get请求传参用params   post传参没有params 
axios.all同时发送多个请求 , 封装函数, 设置返回值

7.接口环境设置

  • 开发上线的不同阶段,需要不同的配置 ----不同的阶段接口是不同的
  • 不同的跨域方式配置不同 -----设置跨域方式统一更改
  • 打包的饿时候统一注入环境参数,统一管理环境,输出不同的版本包

–mode配置参数将环境变量给项目

conrs环境下配置 不同跨域方式配置

"serve": "vue-cli-service serve --mode=development",
 "build": "vue-cli-service build --mode=production"
 // 环境配置文件  创建env.js文件
// 进行判断时进行什么方式的跨域处理
let baseURL
switch (process.env.NODE_ENV) { 
  case 'development':  
    baseURL = 'http://dev-mall-pre.springboot.cn/api'
    break
  case 'test':
    baseURL = 'http://test-mall-pre.springboot.cn/api'
    break
  case 'prev':
    baseURL = 'http://prev-mall-pre.springboot.cn/api'
    break
  case 'prod':
    baseURL = 'http://mall-pre.springboot.cn/api'
    break
  default:
    baseURL = 'http://mall-pre.springboot.cn/api'
    break
}

export default {
  baseURL,
}

如果是proxy代理方式不需要设置, 需要改 vue.config.js中转接地址

8.mock设置模拟数据

  • 本地创建json
  • easy-mock平台
  • 继承mock-api

ebpack my-project

### 4.vue脚手架的自定义配置

`1.通过package.json配置项目`

```js
必须是符合规范合法的json语法,在最底部设置
"vue" :{
  	"devServer": {
      "port":"8000",
        "open": true}
}

2.以上做法不推荐, 单独定义到vue.config.js文件中国进行配置

在项目根目录文件创建vue.config.js

在改文件中农进行相关配置,从而覆盖法默认配值

module.exports = {
  devServer: {
    port: 8888,
    open: true
  }
};

7.element-ui基本使用

vue2.0的桌面组件库:省省略美化样式的时间

1基于命令行方式的手动安装

步骤:

1.安装依赖包 npm i element-ui -S

2.导入Element-UI相关资源

//导入组件库
import ElementUI from 'element-ui';
//导入组件相关样式
import 'element-ui/lib/theme-chalk/index.css
//配置Vue插件
Vue.use(ElementUI)

2.基于图形化界面自动安装

  1. 运行vue ui 命令
  2. 通过vue项目管理器计入具体的项目配置面板
  3. 点击插件 添加插件 进入插件查询面板
  4. 搜索vue-cli-pligin-element并安装
  5. 配置插件, 实现按需导入, 从而减少打包的项目的体积

vue.config.js中关闭语法检测

lintOnSave:false,
   devServer: {
       overlay:{
           warning:false,
           errors:false
       },
       ...
}

前项目技术栈

vue
vue-router
element-ui
axios
echarts

后端技术栈

node.js
express
jwt  //状态保持工具,实现登录记录功能
mysql
sequelize  前后端项目分离模式

8.前段项目

1.项目初始化

  1. 安装vue脚手架
  2. 通过vue脚手架创建项目 vue ui创建项目
  3. 配置vue路由
  4. 配置element-ui 组件库
  5. 配置axios库,安装axios依赖,运行依赖
  6. 初始化git远程仓库
  7. 将本地项目托管到github或者码云中

步骤

###git ee安装公钥

添加公钥成功之后, 在终端输入
ssh -T git@gitee.com
是否添加到可信任列表中
yes

gitee上传绑定邮箱账号

账号 :wangwanqi999
密码 :wangwanqi999

后台环境安装配置

安装mysql数据库
安装node.js环境
配置项目相关信息
启动项目
使用postman测试后台项目接口是否正常

启动数据库 解压apiserver,导入数据

在apiserver目录下运行npm install命令,安装依赖包

上述

模块化语法

1.下载安装配置node.js版本文件

2.下载安装git

git需要path路径,配置密匙

点击右下角图标 —— ctrl shift p 输入git 命令,将选中的分支合并到当前分支

1.vs创建分支

点击创建新的分支, 输入分支名称.点击云图标,上传至git

3.安装插件

vue ——高亮语法

3创建项目

vue ui 创建项目 安装lint 开发依赖

图纸 imooc_xiaomi@163.com

4.安装

5本地存储

cookie , storage 区别

  • 存储大小 : cookie 存储4k(有时候存储大量的报文. 内存不够) , storage 5m
  • 有效期: cookie拥有有效期,过期之后cookie会自动消失, 存储在内存中, storage只存储在浏览器端
  • 路径:cookie有路径限制, storage只 pi: cookie没有特定的api , storage有对应的api
  • cookie会自动发送到服务器端, 用作用户唯一凭证 , storage只存储在域名下

6.接口统一拦截

  • 统一报错
  • 未登录统一拦截 返回login页面
  • 请求值, 返回值统一处理
get请求传参用params   post传参没有params 
axios.all同时发送多个请求 , 封装函数, 设置返回值

7.接口环境设置

  • 开发上线的不同阶段,需要不同的配置 ----不同的阶段接口是不同的
  • 不同的跨域方式配置不同 -----设置跨域方式统一更改
  • 打包的饿时候统一注入环境参数,统一管理环境,输出不同的版本包

–mode配置参数将环境变量给项目

conrs环境下配置 不同跨域方式配置

"serve": "vue-cli-service serve --mode=development",
 "build": "vue-cli-service build --mode=production"
 // 环境配置文件  创建env.js文件
// 进行判断时进行什么方式的跨域处理
let baseURL
switch (process.env.NODE_ENV) { 
  case 'development':  
    baseURL = 'http://dev-mall-pre.springboot.cn/api'
    break
  case 'test':
    baseURL = 'http://test-mall-pre.springboot.cn/api'
    break
  case 'prev':
    baseURL = 'http://prev-mall-pre.springboot.cn/api'
    break
  case 'prod':
    baseURL = 'http://mall-pre.springboot.cn/api'
    break
  default:
    baseURL = 'http://mall-pre.springboot.cn/api'
    break
}

export default {
  baseURL,
}

如果是proxy代理方式不需要设置, 需要改 vue.config.js中转接地址

8.mock设置模拟数据

  • 本地创建json
  • easy-mock平台
  • 继承mock-api