Vue3学习笔记

147 阅读13分钟

vue3学习笔记

vue基础

1-1 组件的概念

组件就是页面中的一部分,最小粒度的组件其实可以是一个html 的标签

     // createApp 表示创建一个vue应用,存储到 app变量中
    //传入的参数表示,这个应用最外层的组件,应该如何展示
    // mvvm 设计模式,m -> model 数据,v ->view 视图,vm ->viewModel  视图数据连接层;在vue中代表的是一个一个的组件
    const app = Vue.createApp({  //创建一个vue应用 
        data(){
            return {
                message:'hello world'
            }
        },
        template:"<div>{{message}}</div>"
    })
    // vm 代表的就是 vue 应用的根组件
  const vm =   app.mount('#root')   // 只挂载到div 是 root的下面

1-2 Vue中的生命周期函数

// 使用vm.unmount() 触发数据销毁
​
    //生命周期函数:在某一时刻自动执行的函数
    const app = Vue.createApp({
        data(){
            return {
                message:'hello world'
            }
        },
        // 在实例生成之前会自动执行的函数
        beforeCreate() {
           console.log('beforeCreate') 
        },
        // 在实例生成之后会自动执行的函数
        created() {
            console.log('created')
        },
        //在组件内容被渲染到页面之前 立即自动执行的函数
        beforeMount() {
           
            console.log( document.getElementById('root').innerHTML,'beforeMount')
        },
        // 在组件内容被渲染到页面之后自动执行的函数
        mounted() {
            console.log( document.getElementById('root').innerHTML,'mounted')
        },
        // 当数据发生变化时会自动执行
        beforeUpdate() {
            console.log(document.getElementById('root').innerHTML,'beforeUpdate')
           
        },
        // 当数据发生变化,同时页面完成更新后,会自动执行的函数
        updated() {
            console.log( document.getElementById('root').innerHTML,'updated')
        },
        // 当Vue 应用失效时,自动执行的函数
        beforeUnmount() {
            console.log( document.getElementById('root').innerHTML,'beforeUnmount')
        },
        // 当vue 应用失效时,且 dom 完全销毁之后,自动执行的函数
        unmounted() {
            console.log( document.getElementById('root').innerHTML,'unmounted')
        },
        template:"<div>{{message}}</div>"
    })
    const vm = app.mount('#root')

1-3 模板语法

template:`<div 
        v-bind:title="message"
         v-html="message"
         :[name] = "message"
         @[event] = "handleClick"
         >
         {{message}}
         </div>
         <form action="http://baodi.com" @click = "handle">
            <button type="submit">提交</button>
            </form>
         `  
         //v-html   使用html的形式在页面上展示
 // v-bind:title="message" : 绑定属性值;
 //  v-once   div里面的变量只使用一次,在次更改message的时候不会改变值,降低无用的渲染
  // v-if
  // v-on  @事件的绑定   动态绑定 @[event] = "handleClick"
  //属性名不定,动态绑定  :[name] = "message"
// 提交阻止默认行为  @click = "handle"     e.preventDefault();  
// 修饰符直接阻止默认行为   @click.prevent = "handle"

1-4 数据方法计算属性和侦听器

// computed 和 methods 都能实现的功能,建议使用computed 因为有缓存 // computed 和 watcher 都能实现的功能,建议使用computed 因为更加简洁

    data(){
                return {
                    message:'hello world',
                    count:2,
                    price:5,
                    newTotal:10
                }
            },
            watch:{
                //price 发生变化时,函数会执行
                price(current,prev){
                    this.newTotal = current * this.count
                    // setTimeout(()=>{   // 当数据改变后,3m执行
                    //     console.log('price changed')
                    // },3000)
                }
            },
            computed:{
                // 当计算属性依赖的内容发生变更时,才会重新计算
                total(){
                    return Date.now()
                    // return this.count * this.price
                }
            },
            methods: {
               formatString(string) {
                return string.toUpperCase()
               } ,
               getTotal(){
                //只要页面重新渲染,才会重新计算
                return Date.now()
                // return this.count * this.price
               }
            },
            template:`
            <div>{{formatString(message)}}</div>
            <div>{{total}} {{newTotal}}</div>
            `
​
        })
 /** 
     * data  定义数据
       methods
     1  定义函数的时候 不能写成箭头函数的形式,因为箭头函数的this不会指向vue实例
      比如 handleClickL: () => {console.log(this)}  指向window 
     2 可以在插值表达式中使用定义的方法
computed  当既可以用计算属性也可以用方法的时候,建议用计算属性
watcher 侦听器
     */

1-5 样式绑定语法

  • 1 通过字符串形式控制样式展示 :classString:'red'
  • 2 对象或是数组形式 classObject:{red:true,green:true}, classArray:['red','green',{blue:true}], 3 :class="$attrs.class" 子组件上的class样式是父组件属性上的值

1-6条件渲染

v-if 控制元素在 dom上的存在与否,来控制显示隐藏的 v-show 通过 display:none 来控制隐藏

1-7列表循环渲染

  data(){
        return {
            listArray:['dell','lee','teacher'],
            listObject:{
                firstName:'dell',
                lastName:'yee',
                job:'student'
            }
        }
       },
       methods: {
        handleAdd(){
            //1 使用数组的变更函数push ,pop,shift,unshift,slice,sort,reverse
            // this.listArray.push('hello')  // 从下增加
            // this.listArray.pop()  // 从下删除
            // this.listArray.shift()  //从上删除
            // this.listArray.unshift('aaa') // 从上增加 
            // this.listArray.reverse()  // 反转
            //2 直接替换数组  改变了数组的引用
        //   this.listArray = ['AAA','BBB']
        //   this.listArray = ['aaa'].concat(['world'])
        //   this.listArray = ['aaa','bbb'].filter(item => item ==='aaa')
        //    3 直接更新数组的内容
        // this.listArray[1] = 'hello'
​
        // 直接添加对象的内容,也可以自动的展示出来
        this.listObject.age = 100
        this.listObject.sex = 'male'
        }
       },
       template:`
       <div v-for="(item,index) in listArray" :key="index">
        {{item}}  --  {{index}}
        </div>
        <br>
        // 当v-for 和v-if 在一个标签上使用时, v-if不生效,v-for 优先级高于 v-if
        // 需要同时使用的时候,可以在外层添加一个template,类似于占位符,避免选项多包裹一层div,
        // 把v-if 写在div上   v-if="key !=='lastName'" 可以去掉key =lastName的项
        <template 
        v-for="(value,key,index) in listObject" 
        :key="index"   
        >
        <div v-if="key !=='lastName'">{{value}}  --  {{key}}</div>
        </template>
        <button @click="handleAdd">新增</button>
        <div v-for="item in 10">{{item}} </div>
       `
    })

1-8 事件绑定

 /** 
         * 1 调用多个函数的调用 @click="handleBtn(),handleBtn1()"
         * 2 @click.self = "handleBtn"  //只要点击自己的时候才会触发
         * 3 事件修饰符 prevent 阻止默认行为
         *       capture  事件的运营模式编程捕获的形式
         *       once   事件绑定只执行一次
         *       stop 用来防止冒泡
         * 4 按键修饰符
            @keydown.enter   tab  delete  esc  up down left right
         5 鼠标修饰符:left  right  middle
         6 精确修饰符:exact
         * 
        */

1-9 双向绑定指令的使用

2-1 全局组件和局部组件

  • 组件的定义 app.component 组件的复用性 组件里面的数据是单独被独享的,不会被组件共用
  • 全局组件,只要定义,处处可以使用,性能不高,但是使用起来简单 app.component
  • 局部组件 要注册之后才能使用,性能比较高,使用起来有些麻烦,建议大写字母开头,驼峰命名 局部组件使用时,要做一个名字和组件间的映射对象,你不写映射,Vue底层也会帮你尝试做映射 components:{'dell':counter}, 如果组件名字和标签一样,可以省略 components:{'counter':counter}, 简写 components:{counter}
  const Counter = {
    data(){
        return{
            count:1
        }
    },
   
    template:`<div @click="count +=1">{{count}}</div>`
  }
  const HelloWorld = {
    template:`<div>helo111</div>`
  }
        const app =Vue.createApp({
           components:{
            'dell':Counter,
        //   ' hello-world': HelloWorld,
        //   'counter':Counter,
        HelloWorld,Counter   //这样也会自动映射成上面的形式
        },
            template:`
            <div>
                <dell />
                <hello-world />
                <counter />
                </div>
            `
        })

2-2 组件间传值和校验

    /**
    type  string bollean,Array,Object,Function,Symbol
    required 必填
     default  默认值
     父组件向子组件传值:父:参数的形式 :content1="num" ; 子: props 接收
     动态传参 :content1="num"
        props:{     接收一个content参数,类型是number,比传
            content:{
                type:Number,
                required:true,
                default:222,
                default:()=>{   // 也可以一个函数
                    return  222
                },
                validator:function(){   //校验
                    return value < 1000
                }   
            }
        }
    <div> <test v-bind="params" /> </div> 等价于
    <div> <test :a="params.a" :b="params.b" :c="params.c" /> </div>
属性传的时候,使用content-abc这种命名,接的时候,使用contentAbc命名
<div> <test :content-abc="content" /> </div>
props:['contentAbc']
​
    */

单向数据流的理解: 子组件可以使用父组件传递过来的数据,但是子组件里绝对不能修改传递过来的数据

2-3 non-props 属性

/** *non-props 属性 :指的就是父组件向子组件传值的时候,不会被接收的属性 使用:在模板里面 通过 v-bind = "attrs"mountedthis.attrs" mounted里 this.attrs */

    template:`
            <div>
                <counter msg="hello" msg1="hello1" />
                </div>
            `
        })
        app.component('counter',{
            // props:['msg'],
            // inheritAttrs:false,  // div上不会有msg属性
            mounted() {
                console.log(this.$attrs.msg)
            },
            template:`
            <div v-bind:mag="$attrs.msg">Counter</div>  // 得到某一个属性
            <div v-bind="$attrs">Counter</div> // 把父组件传过来的所有属性在这个标签上展示
            <div>Counter</div>
            `
        })

2-4父子组件事件通信

/**
     子组件告诉父组件,让父组件来修改count值  在组件里调用this.$emit(adOne);
      父组件监听@add-one="handleAddOne"
      注意:子组件触发的时候使用驼峰命名 addOne;父组件监听的时候使用 横线连接add-one
  emits:['add']  表示组件会向外触发 add 这个事件;它的意义是可以明显的知道向外触发了哪些事件
  父子组件存在双向绑定的时候,可以使用
     父: <counter v-mode="count" />
     子: props:[modelValue]    this.$emit('updata:modeValue',this.modelValue +3)
     渲染的时候 {{modelValue}} 
     备注:modelValue  和updata:modelValue是固定语法,
     如果想更换 modelValue的值  在父组件上的v-model:app
     可以在父 :<counter v-mode:app="count" />
     子: props:[app]    this.$emit('updata:app',this.app +3)
     渲染也用{{app}}
     
    */

2-5 组件间双向绑定高级内容

// 如果一个子组件有多个数据想通过 v-model 和父组件的 的data建立关系的时候, 可以在后面加冒号跟参数名字 v-model:title 可以写多个v-model 的绑定

修饰符:v-model.uppercase 在子组件上通过modelModifiers接收 props: { 'modelValue':String, 'modelModifiers':{ // modelModifiers 默认语法 default: ()=>{ // 默认值,不传的时候是一个空对象

            }
        }
       },

2-6 使用插槽和具名插槽解决组件内容传递问题

/**
     调用子组件内部的一个东西 slot 插槽
     如果父组件想往子组件传递一些dom 节点或是元素标签的时候,没有必要通过属性的方式传递,可以使用插槽
     使用slot 希望可以定制
     slot 中使用的数据,作用域问题
     父模板里调用的数据属性,使用的都是父模板里的数据
     子模板里调用的数据属性,使用的都是子模板里的数据

具名插槽:把插槽拆分几部分,每个部分分开调用,给每片段都命名上名字 v-slot 不能直接写在标签上,需要写在 上,加一个占位符

使用

插槽的简写 v-solt:header 等价于 #header 作用域插槽:解决的问题,当子组件渲染的内容由父组件决定的时候,可以使用作用域插槽 比如怎么展示列表,能够让父组件调用子组件里面item的数据 父: 这里也可以直接使用结构的语法 {{slotProps.item}} // 这里直接使用{{item}} 子:

*/

2-7动态组件和异步组件

 // 动态组件
            // <input-item v-show="currentItem ==='input-item'" />
            // <input-text v-show="currentItem ==='input-text'"/> 
            // 上面这两句可以使用动态语法替换  <component :is="currentItem" /> 
            // template:` 
            // <keep-alive>
            // <component :is="currentItem" /> 
            // </keep-alive> 
            // <button @click="handleClick">切换</button>
            // `,
    /**
     * 动态组件:根据数据的变化,结合component这个标签,来随时动态切换组件的实现
     <component :is="currentItem" /> 要显示一个组件,由currentItem决定,直接获得数据,做更改
     在使用动态组件的时候,会有一些问题,比如之前的输入会清除,可以使用<keep-alive>缓存
        <keep-alive>
        <component :is="currentItem" /> 
        </keep-alive> 
     异步组件:异步执行某些组件的逻辑 
     <input-text /> 在调用的时候,这个组件会立马执行
    创建一个异步组件

通过异步的方式,动态的加载一些组件,好处,把大型项目拆分很多小的js文件

   app.component('async-common-item',Vue.defineAsyncComponent(()=>{ return new Promise((resolive,reject)=>{ 
          })
    }))

 

2-8查漏补缺

v-once 让某个元素标签只被渲染一次 ref 1 实际上是获取dom 节点/或是组件引用的一个语法 在页面渲染完毕后,需要操作或是获取dom,可以使用ref引用的方式

mounted(){ this.$refs.count } provide / inject 父组件传给孙子的时候,通过 props 传给子,在传给 孙 ..... ,如果有多级会很麻烦

  • 父:provide:{ 提供数据 count:1 } //子组件不需要传递
  • 孙:inject:['count'] 跨越多层组件使用 如果想把父组件里面 data里的数据传递下来,需要把provide写成函数
  • 父:provide(){ return {count:this.count} } 但是这种传递的方式是一次性的,如果data里面的数据改变,孙子组件里面的数据不会从新渲染到页面上,解决办法 --vue3 后续更新

Vue 和 css动画效果

3-1 vue实现基础的css过度与动画效果

过度:从一个状态到缓慢到另一个状态 动画:一个元素运动的情况 1 通过class 名字控制

hello world
2 通过style 控制
过度1

3-2 使用transition 标签实现 单元素组件的过度和动画效果

单元素 , 单组件的入场 出场动画 单元素:

    <div >hello world</div> 就是一个单元素,下面没有其他标签 
  • 入场:从隐藏 -- 展示
  • 出厂:从展示 -- 隐藏
  • transition 标签 需要配合一些固定的css样式才会有效果 .v-enter-from
  • 固定的样式名字 入场样式
      .v-enter-from { opacity: 0; } 
      v-enter-active   // 过度效果是什么样式的 
    v-enter-active { transition:opacity 3s ease-out ; }
    .v-enter-to { opacity: 1; }
  • 出场动画:
     .v-leave-from { // 此处可以省略,效果不受影响 opacity: 1; }
    .v-leave-active{ transition:opacity 3s ease-in ; } 
    .v-leave-to{ opacity: 0; } 
  • 更改固定的 v-enter-from 名字
     1 <transition name="hello"> hello-enter-from 以hello开头
    2 <transition leave-active-class ="bye"> .bye 自定义动画名字 自定义动画名字好处:可以做复杂的动画效果,或是动画效果库 比如 animate.css动画库

可以给元素添加过渡和动画效果 通过type 控制以哪一个为准结束动画和过渡 :duration = 1000 直接定义 或是定义一个对象 :duration{enter:1000,leave:3000}

js动画 钩子函数 @before-enter ="handleBeforeEnter" 接收一个参数 el 元素 //在动画进入之前 @enter="handleEnterActive" el ,done //在动画执行过程中 clearInterval(animation) // 结束动画 在调用done() 才算结束 @after-enter ="handleEnterEnd" // 动画执行后调用的函数

3-3 组件和元素切换动画

    /**
     *多个单元素标签动画切换
     期望实现 一个隐藏完毕,另一个在展示
     在 transition上添加 out-in 先隐藏,在展示  <transition mode="out-in">
        in-out  先进来,在隐藏
     注:如果不添加,会两个一起执行

执行刷新页面就有动画 添加 appear 属性

多个单组件之间的切换
<aompon-a v-if="show"></aompon-a>
<aompon-b else-if="show"></aompon-b>

1 v-if v-else 2 动态组件也可以实现

3-4 列表动画

{{item}} .v-move { transition: opacity .5s ease-in }

状态动画
通说逻辑改变动画效果,比如 从 1 到 10数字的变化
SVG 
通过数字来控制展示的效果

4-1 Mixin混入的基础语法

/** mixin 混入 把一些内容混入到那里去 mixins:[myMixin], // 在vue的实例上使用 myMixin data 可以混入 // 组件data,methods 优先级高于mixin data优先级 1 当组件中没有对应的数据的时候,会使用混入的数据

2 2 当组件中有对应的数据的时候,会使用组件中的数据
{{number}}
1 生命周期函数:先执行mixin里面的 ,在执行组件里的 全局定义和局部定义 app.mixin 全局定义 全局定义mixin,不用声明也会注入进来 const myMixin 局部定义

自定义的属性,(不在data中,直接定义的属性)组件中的属性优先级高于 minxin 属性的优先级

自定义属性,修改优先级 自定义合并属性策略修改 // 优先使用minxin的 app.config.optionMergeStrategies.number = (mixinVal,appValue) => { return mixinVal || appValue // 如果minxin 有value 就用minxin,否则就用app的 }

// 这种方式定义的是局部的minxin,使用的时候,需要在组件里添加 mixins:[myMixin], 才可以使用

4-2 Vue中的自定义指令

//全局定义
    // app.directive('focus',{  // 定义focus指令
    //     mounted(el) {  //el 当前的元素
    //         el.focus()
    //     },
​
    // })

局部定义 const directives = { focus:{ mounted(el) { //el 当前的元素 el.focus() }, } }

4-3 Teleport 传送门功能

/** * teleport传送门 把一个组件的某些元素或是一个组件直接挂到其他dom上 比如一些模态框 蒙层 < teleport to=""> < /teleport>

4-4 render函数

 template在底层被编译后会生成render函数

render 调用Vue的 h 方法,去返回的一个内容,这个内容就是虚拟dom //虚拟dom -- dom节点 js对象的表述 对真实dom的映射 // 1 性能更好 // 2 Vue具有跨平台的能力,去编写移动端的内容 // { // tagName:'div', // test:'hello', // attributes:{}

总结: template ---》 render --> h --》 虚拟dom(js对象)--》真实 DOM -> 展示到页面上

4-5 插件的定义和使用

plugin 插件 把一些通用性的功能封装起来 定义:

 const myPlugin = { install(app,options){ // 两个参数,app 是vue的实例,options 就是调用传递的对象{name:'dell'}
    }
}
使用 :app.use(myPlugin)

5-1 setup函数的使用

  • 1 产生的背景 当组件越来越大的时候,传统的Vue定义 data,methods (分开定义)维护性困难 vue3 的compositions API 可以解决这种问题
  • 2 使用 setup 函数: 在组件created 实例被完全初始化之前 setup(props,context) 接收2个参数 ;props外部组件传递过来的内容,contenxt上下文 在setup里不能使用this 备注:compositions API 所有代码编写要建立在 setup函数之上,这个函数是实例被完全初始化之前调用的 会return 出去一些数据,这些数据会被 template使用
  setup(props,context){
            return {
                name:'dell',
                handleClick:()=>{
                    alert(123)
                }
​
            }
​
        },

5-2 ref和reactive响应式的用法

原理: 通过proxy 对函数进行封装,当数据变化时,触发模板等内容的更新 ref:处理基础类型的数据

引用的作用:当改变值的时候,页面是可以渲染出来的

reactive :处理非基础类型的数据

roRefs 原理 proxy ({name:'dell'}) 转化成 {name:proxy{value:'dell'} const {name} = toRefs(nameObj) //直接使用reactive不可以直接使用name做响应式的,需要使用toRefs做转化

        setup(props,context){
                const { ref } = Vue
                // proxy ref 把 'dell' 变成proxy({value:'dell'})这样的响应式引用
                let name = ref('dell')
                setTimeout(()=>{
                    name.value='lee'
                },2000)
                return {name}
​
                const { reactive } = Vue
                // proxy  ,{name:'dell'} 变成了proxy({name:'dell'})这样的响应式引用
                const nameObj = reactive({name:'dell'})
                setTimeout(()=>{
                    nameObj.name = 'lee1'
                },2000)
                return {nameObj}
            },
​

5-3 toRef 以及context参数

  toRefs  如果是一个对象里没有对应的属性值,比如age,toRefs是不会做更改的
     解决办法,使用toRef   const age = toRef(data,'age')
 context有三个值

attrs 父组件传递过来的 None-Props 属性 slots 父组件传递过来的插槽 替换 this.slotsemit向外触发事件传统语法this.slots emit 向外触发事件 传统语法this.emit

    setup(props,context){ 
    const {reactive,toRef} = Vue 
    const data = reactive({name:'dell'}) 
    const age = toRef(data,'age') 
    // const {name} = toRefs(data) //name 被转化成 refs setTimeout(()=>{ age.value = 'lee' },2000)

5-4 CompositionAPI 开发 tolist

做了两件事 1 改变input的值 2 往list里放数据

5-5 computed 方法生成的计算属性

  copmputed 计算属性
     1 接收一个函数
      computed (()=>{
                return count.value + 5
            })
    2 接收一个对象 ,有两个方法 set get
     let countAddFive = computed({
            get:() => {
                return count.value + 5
            },
           set:()=>{
             count.value = 10
            }
         })

5-6 vatch 和 watchEffect的使用差异

watch 具备一定的惰性 ,首次页面展示不执行,只有改变的时候才会执行 参数可以拿到原始和当前值

  • 1 监听的是一个ref watch(name,(currentValue,prevValue) => { console.log(currentValue,prevValue) })
  • 2 如果监听的是一个reactive 数据 需要在参数 前面写一个箭头函数 watch( () => nameObj.name,(currentValue,prevValue) => { console.log(currentValue,prevValue) })
  • 3 监听多个数据的变化,用一个侦听器承载 -- 参数接收一个数组 watch( [() => nameObj.name,() => nameObj.englishName], ([curName,engcur],[prevName,prevEng]) => { console.log(currentValue,prevValue) })

watchEffect 侦听器,偏向于effect

  • 1 立即执行,没有惰性
  • 2 当数据改变的时候,如果对应的数据有依赖,就会侦听;如果没有,就不会侦听 监听器失效:可以添加一个定时器 watch 可以配置第三个参数,immediate:true 就会立即执行
差异
  • 1 立即执行,没有惰性
  • 2 不需要传递你要侦听的内容,自动会感知代码依赖,不需要传递很多参数,只要传递一个回调函数
  • 3 watchEffect 不能获取之前数据的值

5-7 生命周期函数

把生命周期函数z在 setup中引入   const {onBeforeMount} = Vue
onBeforeUnmount  子组件的显示和隐藏会触发
在 CompositionAPI 有两个生命周期函数是没有的

beforeCreate created 这是因为setup 函数执行时间在这两个周期之间 onRenderTracked 每次渲染后重新收集响应式依赖 onRenderTriggered 每次触发页面重新渲染时自动执行

5-8 Provide inject ref

    谁提供的数据,在哪里修改
​
     dom ref  
     在setup中获取dom
     const hello = ref(null)

获取一个真实的dom节点 setup(){ const {ref,onMounted} = Vue const hello = ref(null) // 这里的ref生成的一个响应式的引用 onMounted(() => { console.log(hello.value) }) return {hello} }, //ref 获取一个dom节点的引用,这两个不一样,单需要配合使用 template:<div ref="hello"> hello world </div>

6-1 VueCli 的使用和单文件组件

    1 先安装 node LTS 稳定版本 node 和 npm 会一起安装上 
    2 安装nrm npm install -g nrm 会有很多国内的镜像源 
    nrm ls 查看所有的镜像源 
    nrm use xxx 使用的镜像源
    vue-cli:vue3.0之前版本使用此名称
    @vue/cli:vue3.0之后版本包括3.0版本使用此名称 
  //  清除之前的脚手架 
    //卸载3.0之前的版本
    npm uninstall -g vue-cli
    yarn global remove vue-cli 
    //卸载3.0之后的版本(可以统一使用此指令卸载) 
    npm uninstall -g @vue/cli 
    yarn global remove @vue/cli 
   // 安装最新的版本 
    npm install -g @vue/cli 或者 yarn global add @vue/cli 安装指定版本 
    //安装2.9.6版本
    npm install -g vue-cli@2.9.6 
    yarn global add vue-cli@2.9.6 
    //安装3.0.3版本 
    npm install -g @vue/cli@3.0.3
    yarn global add @vue/cli@3.0.3 
    //安装4.0.5版本 
    npm install -g @vue/cli@4.0.5
    yarn global add @vue/cli@4.0.5

入口文件 main.js 创建一个app应用 挂载到节点上 createApp(App).mount('#app') app.vue

单文件组件 -- 这个文件就是一个组件 模板 样式 逻辑在一个.vue文件里,就形成了一个单文件组件

6-2Vue-router路由的理解和使用

路由是指根据 url 的不同,展示不同的内容 指跳转路由的标签,跳转不同的路由里面去 负责展示当前路由对应的组件内容

component: () => import('../views/AboutView.vue') 异步懒加载路由 一开始加载打开的时候没有加载about组件,当访问的时候才会加载 可以降低首屏加载量,带来的影响,当点击切换页面的时候,可能会加载的慢

6-3 Vue 的语法解析

  • 为什么要使用vuex

  • vueX 数据管理框架

    • 当项目变得越来越复杂,使用props project来传递数据 可维护性不太好 VueX创建了一个全局唯一的仓库,用来存放全局的数据 createStore 存放全局的数据在state里面 定义 :state:{name:'dell'} 使用/获取:在页面写一个计算属性: computed:{ myName(){ return this.$store.state.name } }
  • 修改全局的数据

    • 1 不能随便修改,需要一套完整的机制才可以修改 流程: 想改变数据,
    vuex 要求第一步,必须派发一个action this.$store.dispatch('change') // dispatch就是派发;change 就是一个action 派发一个叫change 的action

   回到仓库的代码里,就有一个actions actions:{ //第二步,store感知到你触发了一个叫change的action,执行change方法 change(){ // 第三步 , 提交一个commit ,触发一个mutation this.commit('change') // 这个mutation名字叫 change } }

     mutation:{ //第四步,对应的mutation 被执行 change(){ // 第五步 在mutation里面修改数据 this.state.name = 'lee' } }

总结: 1 dispatch 方法,派发一耳光action,名字叫做change 
      2 感知到 change这个action,执行store中actions 下面的change 
      3 commit 提交一个叫做change 的数据改变 
      4 mutation感知到提交的change改变,执行change方法改变数据

为什么要存在actions 
    在没有异步的情况下,可以直接commit修改数据,省略第2this.$store.commit('change')
    mutation里面只允许写同步代码,不允许写异步代码 (写了也不会报错) 
    actions里面可以写 异步代码 
    this.$store.dispatch('change',hello world) 第二个参数是 带过去的数据 
    mutations:{ change(state,str) //对应的第一个参数是
    state state.name = str } 
    actions:{ change(store,str){ // 对应的第一个参数是store 
    store.commit('changge,'str) } }
    dispatch 和actionns 做关联
    commit和mutation 做关联

6-4CompositionAPI中如何使用

    import {useStore} from 'vuex' 
    export default {
    name:'Home',
    setup() {
    const store = useStore()
    const name = store.state.name
    return {name}

} }

6-5 使用axios 发送ajax请求

 axios.post('https://www.fastmock.site/mock/5b04a994a775f6524f683b6e7c843a5e/jingdongvue3/api/user/login',{
        username:'data.username',
        password:'data.password'
     }).then(() => {
        alert('成功')
     }).catch (()=>{
        alert('失败')
     })
//把Content-Type 改成json
axios.defaults.headers.post['Content-Type'] = 'application/json';

异步路由 component: () => import(/* webpackChunkName: "Home" */ '../views/home/Home') 访问哪个页面就加载对应的页面,路

7-1 移动端真机调试

把ip地址直接粘贴到手机浏览器即可访问