Vue2构建项目分析
Vue学习官网
Vue CLI官方
# 全局安装,只要装一次,以管理员身份
npm install -g @vue/cli
# 查看脚手架工具版本
vue --version
# 创建项目,注意路径,名称不能是中文
vue create my-project
# 启动项目,找package.json中的script,看是serve还是dev
npm run serve
项目结构
生成项目如下:
src目录下:
- main.js:运行文件,类似于启动类
- App.vue:app根组件
App.vue 组件通常是根组件,它会被挂载到 index.html 中的 id=“app” 的 DOM 元素上。这个挂载过程通常在 main.js 文件中完成。
下面对main.js进行浅析
import Vue from 'vue' // 导入vue.js核心包
import App from './App.vue' // 导入根组件
Vue.config.productionTip = false // 是否显示生产标识
// 创建vue实例
new Vue({
render: h => h(App), // 返回虚拟dom
}).$mount('#app')
- render 属性(函数)根据组件构建出对应的虚拟DOM树,将虚拟 DOM 树转化为实际 DOM 的工作则由 Vue 内部处理。
.$mount('#app')
相当于el
属性赋值挂载对象
vue组件
组件是一个vue实例。
这个vue实例带名字,同时可复用,不能赋值el
结构很清晰:模版template、逻辑代码script、样式style
- template 只能有一个根节点
- style 默认作用全局,局部作用,在style标签中添加scoped
- data 是个函数
为了保证可复用性,一个组件的 data 选项必须是一个函数
返回的是一个对象,每次调用的时候返回的都是一个新创建的对象
data: function () {
return {
count: 0
}
}
结合了ES6 模块化语法,导出一个 Vue 组件的配置对象,使得该组件可以在其他地方被导入和使用
export default {
...
}
scoped的实现原理:
为当前组件的所有元素添加一个唯一的属性(如 data-v-xxxxxx),给当前的样式上都添上一个属性选择器。
组件注册
类比于局部变量全局变量局部注册按需导入,全局注册无需导入,全局使用。
全局注册通过改变 Vue 构造函数的全局组件注册表,使得每个由 Vue 构造函数创建的实例都可以访问这些注册的组件。
Vue.component('组件名', 组件对象)
组件通信
就是组件之间的数据传递
关系:父子,非父子,vuex处理复杂情况
父传子
父组件向子组件提供数据和修改数据的函数
子组件通过设置property的方式,声明想要获得的数据和函数,父组件通过v-bind给子组件传值,v-on传修改函数
具体操作如下:
-
传值
子组件在对象中添加props,可以是数组,或者对象,父组件直接:属性名="值"
// 字符串数组 props: ['title', 'likes', 'isPublished', 'commentIds', 'author'] // 对象,有校验提示,也可以自定义校验方式 props: { title: String, likes: Number, isPublished: Boolean, commentIds: Array, callback: Function, contactsPromise: Promise // or any other constructor }
-
传修改函数
子组件中调用$emit
函数,相当于在子组件对象中注册并触发一个新事件,同时提供参数
父组件监听该事件,并给出响应函数(修改函数)
由此表现为子组件调用并传递参数给一个在父组件中定义的方法// 子组件 methods: { doSomething() { // 做一些事情 this.$emit('actionHappened', 'some data'); } }
在这里,
doSomething
方法触发了actionHappened
事件,并且向父组件传递了'some data'
作为参数。然后在父组件中,你可能会这样监听这个事件:
<!-- 父组件的模板 --> <child-component @actionHappened="handleAction"></child-component>
在父组件的 JavaScript 部分,你会定义
handleAction
方法来处理这个事件:// 父组件 methods: { handleAction(data) { console.log('Event received with:', data); // 做一些响应事件的处理 } }
非父子
父子组件传递,父组件是可以直接拿到子组件对象的,直接赋值即可
非父子组件,需要一个公共对象,这个对象两个组件都能获取,这里叫“事件总线”
utils\eventBus.js:
import Vue from "vue"
const Bus = new Vue()
export default Bus
A组件:获得Bus对象,给Bus对象中的updateNews
添加函数体:修改A组件中的news属性
<script>
import Bus from '@/utils/eventBus';
export default {
data () {
return {
news: '黑神话悟空榜首'
}
},
created() {
Bus.$on('updateNews',(news)=>{
this.news = news
})
},
}
</script>
B组件:点击按钮调用Bus对象中的updateNews
函数
<template>
<div class="aComponent">
<p>我是B组件</p>
<button @click="changeInfo">修改新闻</button>
</div>
</template>
<script>
import Bus from '../utils/eventBus'
export default {
methods: {
changeInfo(){
Bus.$emit('updateNews','广东多地宣布今起停课')
}
}
}
</script>
跨层级父传后代,vue提供provide & inject 机制
.sync 同步
关于双向数据绑定的原理:
就是两个对象内的变量之间实现值的同步变化
v-model就是数据和视图数据的绑定,属性名为value
在属性名后面加.sync
就相当于自动生成了对应的修改函数,函数名为update:属性名
例子:控制子组件的显示
子组件:添加visable属性,作为v-show的值,添加事件调用修改函数
<template>
<div class="myDialog" v-show="visable">
<button @click="close">关闭对话框</button>
</div>
</template>
<script>
export default {
props: {
visable: Boolean
},
methods:{
close(){
this.$emit('update:visable',false)
}
}
}
</script>
父组件:直接把子组件的visable与isShowDialog进行双向绑定了
<template>
<div class="cComponent">
<p>我是C组件</p>
<button @click="isShowDialog = true">显示对话框</button>
<MyDialog :visable.sync="isShowDialog" ></MyDialog>
</div>
</template>
<script>
import MyDialog from "./MyDialog.vue";
export default {
components: {
MyDialog
},
data () {
return {
isShowDialog: false
}
}
}
</script>
ref属性
操作dom元素需要获得dom元素对象,ref
属性可以类比id
属性
好处:
- 直接
document.querySelector..
作用整个文档,ref
作用当前组件 - vue中组件可视为标签元素,
ref
也可以标记组件,获得组件对象
使用:
- 标签元素上添加
ref
属性 - 获得元素:
this.$refs.值
为了提升性能,vue的dom更新是异步的,$nextTick 函数用于确保在 DOM 更新完成后立即执行某些操作,可以在这个函数里获得更新的dom元素
基于vue-cli自定义创建项目
选择自定义构建
根据需求选择工具
选择无分号规范(标准)
总体选择
ESlint代码规范
规范项目开发中的代码书写风格
JavaScript standard 代码规范的全文
可以根据报错手动修正
也可以使用vscode插件ESLint自动格式化
在vscode setting.json中
// 保存代码不自动格式化
"editor.formatOnSave": true,
// eslint自动修复错误
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
项目打包上线
vue-cli不参与上线,只是协助开发
过程:
将多个文件合并压缩成一个文件
语法降级(babel工具)
less,sass,ts语法解析
脚手架提供的打包命令:npm run build
,最后生成一个dist文件夹
直接生成的文件中使用的是绝对路径,需要配置成相对路径
vue.config.js
文件下进行更改
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
publicPath: './', // 修改成相对路径
transpileDependencies: true
})
直接打包后会将所有js文件合并成一个,js包过于庞大,影响界面加载
官方:vue路由懒加载
在router中把原来引入组件的方式改成下面这种方式