工程化开发&脚手架

工程化开发&脚手架Vue CLI

VueCLI是Vue官方提供的一个全局命令工具。

可以帮助我们快速创建-建一个开发Vue项目的标准化基础架子。【集成了webpack配置】

好处:

  1. 开箱即用,零配置

  2. 内置Babel等工具

  3. 标准化

安装

  1. 全局安装:cmd内输入 yarn global add @vue/clinpm i @vue/cli -g

  2. 查看Vue版本:输入 vue--version

创建

  1. 目录下右键选择 通过code打开 或者 在终端中打开

  2. 输入 vue create projectName(项目名-不能用中文)

  3. 上下键选择 vue2vue3,目前先选vue2

启动

目录下cmd 或者 在vscode打开目录后终端 输入 yarnservenpm run servee (具体是不是 serve 找package.json 中的 scripts)

目录文件介绍

image-20240123235245484.png
  • index.html
image-20240124001047059.png
  • main.js

    文件核心作用:导入App.vue,基于app.vue创建结构渲染index.html

image-20240124001155754.png
image-20240124001615889.png
  • App.vue

    • 渲染

    • 文件组成的三部分(文件要高亮显示需要插件Vetur

    • image-20240124001726421.png
  • template:结构(有且只能一个根元素)

  • script:js逻辑

    • 导出的时当前组件的配置项

    • 里面可以提供data(特殊) methods computed watch 生命周期八大钩子

  • style:样式(可支持less,需要装包)

    • 支持less方法:style标签,lang="less"开启less功能

      装包: yarn add less less-loader -D

普通组件的注册

  1. 局部注册:只能在注册的组件内使用

    在app.vue中

    创建 .vue 文件 (单文件组件)

    在使用的组件内导入并注册

    <script>
    //导入需要注册的组件
    import 组件对象 from '.vue文件路径'
    
    
    export default {
        //局部注册
        components:{
         组件名':组件对象,
     }
    }
    </script>
    

    使用

    当成 html 标签使用 <组件名></组件名>

    组件名规范→大驼峰命名法,如:HmHeader

    <template>
     <div class="app">
            <组件名></组件名>
        </div>
    </template>
    
  1. 全局注册:所有组件内都可以使用

    创建.vue文件 ,在.vue中写组件

    main.js文件中进行全局注册

    //导入需要全局注册的组件
    import 组件名 from './components/HmButton'
    
    //调用Vue.component 进行全局注册
    //Vue.component‘组件名‘,组件对象)
    Vue.component('HmButton', HmButton)
    

    使用

    当成 html 标签使用 <组件名></组件名>

    组件名规范→大驼峰命名法,如:HmHeader

    <template>
     <div class="app">
            <组件名></组件名>
        </div>
    </template>
    

组件的样式冲突

默认情况:写在组件中的样式会全局生效→因此很容易造成多个组件之间的样式冲突问题。

  1. 全局样式:默认组件中的样式会作用到全局

  2. 局部样式:可以给组件加上scoped属性,可以让样式只作用于当前组件

    组件应该有着自己独立的样式,推荐加上scoped

    // 组件的vue文件内
    <style scoped>
        div{
            
        }
    </style>
    

scoped原理:

  1. 当前组件内标签都被添加data-V-hash值的属性
  2. css选择器都被添加[data-v-hash值]的属性选择器最终效果:必须是当前组件的元素,才会有这个自定义属性,才会被这个样式作用到

data函数

在组件中不再写成对象。

一个组件的 data 选项必须是一个函数。→ 保证每个组件实例,维护独立的一份数据对象。

每次创建新的组件实例,都会新执行一次 data 函数,得到一个新对象。

data(){
    return{
        count:100
`   }
}

组件通信

组件通信,就是指组件与组件之间的数据传递

组件的数据是独立的,无法直接访问其他组件的数据

通信用属性传递消息

组件关系:

  1. 父子关系

    • 父组件通过props将数据传递给子组件

      1. 父中给子添加属性传值
      2. 子props 接收
      3. 使用
      // 父组件中
      <template>
         <div>
              <!--1.给组件标签,添加属性的方式,传值-->
              <Son :title="myTitle"></Son>
          </div>
      </template>
          
          
          
      // 子组件中
      <template>
         <div>
              <!--3.模板中直接使用-->
              {{ title }}
          </div>
      </template>
      
      <script>
         export default {
              // 2。子组件内部通过props接收
              props:['title']
          }
      </script>
      
      • Prop 定义:组件上注册的一些自定义属性

        Prop作用:向子组件传递数据

        特点:可以传递任意数量的prop

             可以传递任意类型的prop
        
      • props校验

        // 类型校验
        props:{
         校验的属性名:类型// Number String Boolean Function...
        }
        
        // 完整校验
        props:{
         校验的属性名:{
             type: 类型, // Number String Boolean Function...
             required:true,// 是否必填
             default:默认值,//设置默认值
             validator (value) {
                 //自定义校验逻辑
                 参数为传过来的值    
                 return true/false
             }
         }
        }
        
      • prop & data、单向数据流

        data 的数据是自己的 →随便改

        prop 的数据是外部的→不能直接改,要遵循 单向数据流(单向数据流:父级 prop 的数据更新,会向下流动,影响子组件。这个数据流动是单向的。)

        所以props传过来的数据要修改,需要用函数子传父信息,让父修改,通过单项数据流修改父传过来的数据

  • 子组件利用$emit通知父组件,修改更新

    1. 子$emit发送消息
    2. 父中给子添加消息监听
    3. 父中实现处理函数
// 父组件中
<template>
    <div>
        <!--2.父组件,对消息进行监听-->
        <Son :title="myTitle" @changeTitle="handleChange"></Son>
    </div>
</template>
        
<script>
    import Son from './components/Son.vue'
    exort defaule{
        data(){
            return {
                myTitle:''
            }
        },
        methods:{
            // 3。提供处理函数,提供逻辑
            handleChange (newTitle){
                this.myTitle = newTitle
            }
        }
    }
</script>
    
    
    
// 子组件中
<script>
    export default {
        methods:{
            changeFn(){
                // 1.通过$emit,向父组件发送消息通知
                this.$emit('changeTitle',‘传智教育')
            }
        }
    }
</script>
  1. 非父子关系
  • Vuex

  • event bus

    事件总线

    作用:非父子组件之间,进行简易消息传递。 (复杂场景→Vuex)

    1. 创建 src/utils/EventBus.js(创建一个都能访问到的事件总线 [空的 vue 实例])

      import Vue from'vue'
      const Bus = new Vue()
      export default Bus
      
  1. A组件(接收方),监听 Bus 实例的事件

    <script>
        import Bus from '../utils/EventBus'
        export default{
            created(){
                Bus.$on('sendMsg', (msg) => {
                    this.msg = msg
                })
            }
        }
    </script>
    
  1. B组件(发送方)(可多个),触发 Bus 实例的事件

    <script>
        import Bus from '../utils/EventBus'
        export default{
           methods:{
                clickSend(){
                    //3.B组件(发送方))F触发事件的方式传递参数文(发布消息)
                    Bus.$emit('sendMsg',‘这是一个消息')
                }
            }
        }
    </script>
    
  • provide&inject

    跨层级共享数据。

    1. 父组件 provide 提供数据

      <script>
          export default {
              provide () {
                  return {
                      //普通类型【非响应式】
                      color: this.color,
                      //复杂类型【响应式】
                      userInfo: this.userInfo,
                  }
              }
          }
      </script>
      
  1. 子/孙组件 inject 取值使用

    <script>
        export default {
            inject: ['color','userInfo'],
            created () {
                console.log(this.color, this.userInfo)
            }
        }
    </script>
    

补充:v-model详解

原理:V-model本质上是一个语法糖。例如应用在输入框就是value属性和input事件的合写。

作用:提供数据的双向绑定

① 数据变,视图跟着变:value

② 视图变,数据跟着变 @input

注意:$event用于在模板中获取事件的形参

<template>
    <div id="app" >
        <input v-model="msg" type="text">
        // 等同
        <input :value="msg" @input="msg = $event.target.value" type="text">
    </div>
</template>

表单类组件封装 & v-model简化代码

  1. 表单类组件封装

因为v-model是双向绑定数据,所以会出现子组件修改父组件数据的情况,所以子组件不能写v-model 要拆开写

① 父传子:数据 应该是父组件(数据由父组件提供,方便提交) props 传递过来的,v-model 拆解 绑定数据

②子传父:监听输入,子传父传值给父组件修改

// 父组件
<BaseSelect :cityId="selectId" @事件名="selecteId =$event"/>
// 子组件
<select :value="cityId" @change="handlechange">...</select>

props: {
    cityId: String
},
methods: {
    handleChange (e) {
        this.$emit('事件名',e.target.value)
    }
}
  1. v-model简化代码

    因为v-model是value和input事件的合写

    <BaseSelect v-model="selectId"></BaseSelect>
    // 等同于
    <BaseSelect :value="selectId" @input="selecteId=$event"></BaseSelect>
    

①子组件中:props 通过value 接收,事件触发 input

②父组件中:V-model给组件直接绑数据( :value + @input )

// 子组件
<select :value="value" @change="handlechange">...</select>
props:{
 value: String
},methods: {
 handleChange (e) {
 this.$emit('input', e.target.value)
 }
}
// 父组件
<BaseSelect v-model="selectId"></BaseSelect>

.sync修饰符

作用:可以实现子组件与父组件数据的双向绑定,简化代码

特点:prop属性名可以自定义,非固定为value

本质:属性名@update:属性名 合写

<BaseDialog :visible.sync="isShow" />
// 等同于
<BaseDialog :visible="isShow"  @update:visible="isShow = $event"/>
// 父组件
<BaseDialog :visible.sync="isShow" />

// 子组件
props: {
    visible: Boolean
}
this.$emit('update:visible', false)

ref 和 $refs

用于获取dom元素,或组件实例

  • 获取dom

    1. 目标标签添加 ref属性

      <div ref="chartRef">我是渲染图表的容器</div>
      
    2. 恰当事件,通过 this.$refs.xxx 获取目标标签

      mounted () {
         console.log(this.$refs.chartRef)
      }
      
  • 获取组件实例

    1. 目标组件添加ref属性

      <BaseForm ref="baseForm"></BaseForm>
      
    2. 适当时机,通过this.$refs.xxx,获取目标组件

      就可以调用组件对象里面的方法

      this.$refs.baseForm.组件方法()
      

vue异步更新,$nextTick

vue是异步更新dom的,$nextTick ( 等DOM更更新后,才会触发执行此方法里的函数体 ) 可以在dom更新后做某些事

this.$nextTick(() => {
  代码
})

场景:

  1. 点击编辑,显示编辑框
  2. 让编辑框,立刻获取焦点
this.isShowEdit = true  // 显示输入框
this.$refs.inp.focus()  // 获取焦点

Vue 是异步更新DOM(提升性能),显示之后",立刻获取焦点是不能成功的!

// 正确写法
this.isShowEdit = true  
this.$nextTick(()=>{
    this.$refs.inp.focus() 
})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容