3.使用脚手架
3.1 初始化脚手架
3.1.1说明
(1)Vue脚手架时Vue官方提供的标准化开发工具(开发平台)。
(2)文档 Vue CLI
3.1.2 具体步骤
(1)配置淘宝镜像:npm config set registry https://registry.npm.taobao.org
(2)全局安装@vue/cli。(仅第一次执行)(npm install -g @vue/cli)
(3)切换到项目路径,使用指令创建项目:vue create xxx
(4)启动项目:npm run serve
3.1.3 项目架构
(1).gitignore:配置不接受git管理的文件。
(2)babel.config.js:es6转es5要用到的babel配置文件(不需要修改)。
(3)package.json:
"scripts": { "serve": "vue-cli-service serve",//运行命令 "build": "vue-cli-service build",//代码完成后构建命令,将vue文件转为js,css,html文件 "lint": "vue-cli-service lint"//代码检查 },
(4)package-lock.json:包管理器版本管理。
(5)src:
(5.1)main.js:项目入口文件
/* 项目入口文件 */ //引入vue import Vue from 'vue' //引入App组件,App是所有组件的父组件 import App from './App.vue' //关闭vue生产提示 Vue.config.productionTip = false //创建vue实例对象 new Vue({ //将app组件放入容器中 render: h => h(App), }).$mount('#app')//等于el:"#app"
(5.2)App.vue
(5.3)index.html
<!DOCTYPE html> <html lang=""> <head> <meta charset="utf-8"> <!-- 针对ie浏览器的特殊配置,让ie以最高渲染级别渲染页面 --> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- 开启移动端理想视口 --> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <!-- %= BASE_URL %>指的public下的文件,配置页签图标 --> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <!-- 配置网页标题 --> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <!-- 如果浏览器不支持js,就会渲染标签内内容 --> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <!-- 容器 --> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>
备注:详细参考3.1.5
启动失败原因为:语法检查不通过。
在项目的根目录找到(没有就自行创建)
vue.config.js
文件,关闭语法检查即可const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, lintOnSave:false /*关闭语法检查*/ })
3.1.4 不同版本的VUE
(1)vue.js与vue.runtime.xx.js的区别:
(1.1)vue.js是完整版的VUE,包含核心功能+模板解析器。
(1.2)vue.runtime.xx.js是运行版VUE,只包含核心功能,没有模板解析器。
(2)因为vue.runtime.xx.js没有模板解析器,所以不可以用template配置项,需要使用
render函数,将接受到的createElement函数去指定内容。
3.1.5 修改默认配置
vue隐藏了webpack相关的配置,需要查看可以执行:vue inspect > output.js
可以看到但是无法修改,具体修改方式请参考:
3.2 配置项
3.2.1 ref属性
(1)被用来给元素或子组件注册引用信息(代替id)。
(2)应用在html不爱券商,获取真是dom元素,应用在组件标签上是组件实例对象(vc)。
(3)使用方式:
(3.1)打标识:<h1 ref='title'>Ref属性测试</h1>/ <School ref='school'/>。
(3.2)获取:this.$refs.school/this.$refs.title。
(3.3)获取到子组件之后也可以修改其内部属性。
<template>
<div>
<h1 ref='title'>Ref属性测试</h1>
<button @click='showDom' ref='btn'>点我输出DOM</button>
<School ref='school'/>
<School/>
<School/>
<Student/>
<Student/>
<Student/>
</div>
</template>
<script>
//引入组件
import School from './compnents/School'
import Student from './compnents/Student'
export default {
components:{
School,
Student
},
data() {
return {
}
},methods:{
showDom(){
console.log(this.$refs.title)
console.log(this.$refs.btn )
console.log(this.$refs.school.school.name='this.$refs.school.school.schoolName ')
}
}
}
</script>
<style scoped>
</style>
3.2.2 props属性
功能:让组件接收外部传入数据。
(1)传递数据<Demo name='xxxx'/>
(2)接受数据:
(2.1)props:['name']
(2.2)限制类型
props:{ id:String, name:String, size:String },
(2.3)限制类型,限制是否必填,设置默认值
props: { id: { type: String, //类型 required: true, //是否必填 }, name: String, size: { type: String, //类型 default: "型号(默认)", //是否必填 }, }
(3)备注:props事制度的,Vue底层会检测你对props的修改,如果进行了修改会发出警
告,如果业务需要,那么应该将props的内容复制到data中一份然后修改data中的据。
App.vue
<template>
<div>
<h1 ref="title">Props属性测试</h1>
<button @click="login">登录</button>
<button @click="getMaterial">获取物料</button>
<!-- <Material v-for="m in materialList" :key="m.id" material.materialName="m.materialName" material.id="m.id" material.materialSize="m.materialSize"/> -->
<!-- <Material v-for="m in materialList" :key="m.id" materialName="m.materialName" id="m.id" materialSize="m.materialSize"/> -->
<ul>
<!-- 遍历数组 -->
<!-- <li v-for="material in materialList" :key="material.id">
{{ material.materialName }}
</li> -->
<Material v-for="m in materialList" :key="m.id" :name="m.materialName" :id="m.id" :size="m.materialSize"/>
</ul>
</div>
</template>
<script>
//引入组件
import axios from "axios";
import Material from "./compnents/Material";
const url = "";
export default {
components: {
Material,
},
data() {
return {
token: "",
materialList: [
{
id: "id1",
materialName: "materialName1",
},
{
id: "id2",
materialName: "materialName2",
},
],
};
},
methods: {
//获取物料
getMaterial() {
axios
.get(url + "/data/dataMaterial/list", {
params: {
pageNo: 1,
pageSize: 10,
},
headers: {
"X-Access-Token": this.token,
},
})
.then((response) => {
this.materialList=response.data.result.records;
})
.catch((error) => {
console.error("Error:", error.response.status);
});
/* var xhr = new XMLHttpRequest();
xhr.open("GET", url + "/data/dataMaterial/list");
xhr.setRequestHeader("X-Access-Token", this.token);
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
console.log(xhr);
} else {
console.error("Error:", xhr.status);
}
}
};
xhr.send();*/
},
//登录
login() {
axios
.post(url + "/sys/login", {
username: "ly",
password: "123456",
})
.then((response) => {
this.token = response.data.result.token;
console.log(this.token);
this.getMaterial();
})
.catch((error) => {
console.error(error);
});
},
},
created() {},
};
</script>
<style scoped>
</style>
Material.vue
<template>
<div>
物料信息
<h2>Msg:{{ msg }}</h2>
<h2>物料ID:{{ id }}</h2>
<h2>物料名称:{{ name }}</h2>
<h2>物料尺寸:{{ mySize }}</h2>
<button @click="changeSize">修改物料尺寸</button>
</div>
</template>
<script>
export default {
components: {},
props: {},
data() {
console.log(this);
return {
msg: "这是一个物料",
/* material:{
id:"",
materialSize:"",
materialName:""
}, */
mySize: this.size,
};
},
// propos:["id","size","name"],简单的声明
//限制类型
/* props:{
id:String,
name:String,
size:String
}, */
props: {
id: {
type: String, //类型
required: true, //是否必填
},
name: String,
size: {
type: String, //类型
default: "型号(默认)", //是否必填
},
},
computed: {},
watch: {},
created() {},
mounted() {},
methods: {
changeSize() {
this.mySize="修改物料尺寸"
},
},
};
</script>
<style scoped>
</style>
3.3mxin属性
功能:可以把多个组件共用的配置提取成一个混入对象。
使用方式:
(1)定义混合
export const mixin = { methods: { showName() { alert(this.name) } }, mounted() { //alert("你好啊"+this.name) }, data(){ return { size:"mixinSIze" } } }
(2)使用混入
(2.1)全局混入:import {hunhe} from './mixin'; Vue.mixin(hunhe)。
(2.2)局部混入:import {hunhe} from './mixin';mixins:['hunhe']
(3)注意:data中的数据以源文件为主,methods中的数据都会执行,而且优先执行混入的
Repository.vue
<template>
<div>
物料信息
<h2>Msg:{{ msg }}</h2>
<h2>仓库ID:{{ id }}</h2>
<h2>仓库Size:{{ size }}</h2>
<h2>仓库名称:{{ name }}</h2><button @click="showName">弹框展示名字</button>
</div>
</template>
<script>
import {mixin} from '../mixin'
export default {
components: {},
props: {},
data() {
console.log(this);
return {
msg: "这是一个仓库",
};
},
props: {
id: {
type: String, //类型
required: true, //是否必填
},
name: String,
},
mixins:[
mixin
]
};
</script>
<style scoped>
</style>
Material.vue
<template>
<div>
物料信息
<h2>Msg:{{ msg }}</h2>
<h2>物料ID:{{ id }}</h2>
<h2>物料名称:{{ name }}</h2><button @click="showName">弹框展示名字</button>
<h2>物料尺寸:{{ mySize }}</h2>
</div>
</template>
<script>
//引入一个混合
import {mixin} from '../mixin'
export default {
components: {},
props: {},
data() {
console.log(this);
return {
msg: "这是一个物料",
mySize: this.size,
};
},
props: {
id: {
type: String, //类型
required: true, //是否必填
},
name: String,
size: {
type: String, //类型
default: "型号(默认)", //是否必填
},
},mixins:[
mixin
]
};
</script>
<style scoped>
</style>
mixin.js
//引入Vue
import Vue from 'vue'
//引入app
import App from './App'
import {hunhe} from './mixin'
// Vue.mixin(hunhe)
//关闭提示
Vue.config.productionTip=false
new Vue({
el:"#app",
render:h=>h(App)
})
3.4插件
功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue(vm的原型),第二个以后的
参数是插件使用者传递的数据。
定义插件:
export default { install(Vue,a,b,c){ console.log('install',Vue) //拿到Vue的构造方法,可以进行操作,Vue原型上的方法和属性vm和vc都能使用 //全局过滤器 //Vue.filter() //全局指令 // Vue.directive() //全局混入 // Vue.mixins() //给Vue原型增加方法,属性等等 // Vue.prototype.$myMethod=function(){} // Vue.prototype.prototype="" } }
使用插件:Vue.use()。
3.5 scoped样式
作用:让样式在局部生效防止冲突。
写法:<stype scoped>
3.6 开发流程总结
(1)组件化编码流程
(1.1)拆分静态组件:组件按照功能点拆分,命名不要与html元素冲突。
(1.2)实现动态组件:考虑好数据存放位置,数据是一个组件在用,还是一些都在用。
(1.2.1)一个组件再用:放在自身即可。
(1.2.2)一些组件在用,放在他们共同的父组件上。(状态提升)
(1.3)实现交互:绑定事件。
(2)props适用于:
(2.1)父组件==》子组件 通信。
(2.2)子组件==》父组件 通信(要求父组件先给子组件一个函数)。
(3)v-model使用时要切记,v-model绑定的不能是props传过来的值,因为props内传入的
值是不可以修改的。
(4)props传过来的若是对象型的值,修改对象属性时vue不会报错,但不推荐这样做。
3.7本地存储
webStorage:
(1)储存内容大小一般支持5m左右(浏览器不同也可能不一样)
(2)浏览器通过Window.sessionStorage和window.localStorage属性来实现本地存储机制。
(3)相关API:
(3.1)xxxxxxStorage.setItem(key,vaule);
该方法会把一个兼职顿添加到存储中,如果已有该键,则会更新内容。
(3.2)xxxxxxStorage.getItem(key);
该方法接收一个key作为参数,获取对应的value。
(3.3)xxxxxxStorage.removeteam(key);
该方法接收一个key作为参数,删除对应的key和value。
(3.4)xxxxxxStorage.clear();
清除存储中所有数据。
(4)备注:
(4.1)sessionStorage存储的内容会随着浏览器窗口关闭而消失。
(4.2)localStorage存储的内容需要手动调用相应方法才会消失。
(4.3)xxxxxxStorage.getItem(key);获取不到会返回一个null
(4.4)保存对象时可用:JSON.stringify(person),
解析时用:JSON.parse(localStorage.getItem("personToJson"))
JSON.stringify(null)依然是null
saveData() {
let person = { name: "张三", age: 18 }
localStorage.setItem("msg", "hello!!");
localStorage.setItem("numberMsg", 666);
localStorage.setItem("person",person);
localStorage.setItem("personToJson", JSON.stringify(person));
},
readData() {
let person = { name: "张三", age: 18 }
console.log( localStorage.getItem("msg", "hello!!"));
console.log(localStorage.getItem("numberMsg", 666));
// console.log(localStorage.getItem("person",person));
console.log(JSON.parse(localStorage.getItem("personToJson")));
},
deleteData() {
localStorage.removeItem("msg")
localStorage.removeItem("numberMsg")
localStorage.removeItem("personToJson")
},
clearData(){
localStorage.clear();
}
3.8组件自定义事件
(1)一种组件捡的通信方式,适用于:子组件===》父组件
(2)适用场景:A是父组件,B是子组件,B想给A传值,那么就要在A中给B绑定自定义事
件,事件回调在A中。
(3)绑定自定义事件:
(3.1)再父组件中使用
<student v-on:sendName="getName"></student> <student @sendName="getName"></student>
(3.2)再父组件中使用
<student ref="student" @click.native="show"></student> <script> mounted(){ // this.$refs.student.$once("sendName",this.getName) // this.$refs.student.$on("sendName",this.getName) this.$refs.student.$on("sendName",(name)=>{ console.log("getName被触发了",name); console.log(this); this.studentName=name }) } </script>
(3.3)若想让自定义事件只触发一次,可以用once修饰符或者$once方法。
(4)触发自定义事件: this.$emit(name,value)。
(5)解绑滴定仪事件: this.$off(name)。
(6)组件上也可以绑定原生DOM事件,要用native修饰符。
(7)注意,通过this.$refs.student.$on(name,回调),板顶自定义事件时,回调要么要么在
methods中,要么用箭头函数,否则this会指向调用函数的实体。
3.9 ★全局事件总线★
(1)全局事件总线(GlobalEventBus)是一种组件之间通信的方式,适用于任意组件之间
的通信。
(2)安装全局事件总线:
beforeCreate(){ Vue.prototype.$bus=this }
(3)使用全局事件总线:
(3.1)接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,回调由A
组件自身实现。
mounted(){ this.$bus.$on('hello',(data)=>{ console.log('School组件收到了',data) }) }
(3.2)提供数据
this.$bus.$emit('hello',this.student.name)
(4)使用完毕后,组件销毁之前最好用$off解绑当前组件所使用的事件
beforeDestroy(){ this.$bus.$off('hello') },
3.10 消息订阅与发布
(1)消息订阅预发布(pubsub)是一种组件间的通信方式,适用于任意组件通信。
(2)使用步骤:
(2.1)安装pubsub:npm i pubsub-js。
(2.2)引入import pubsub from 'pubsub-js'
(2.3)接收数据:A组件接收数据则在A组件内订阅消息,回调函数由A实现::
this.pubId=pubsub.subscribe('getStudentName',(msgName,data)=>{ })
第一个参数为消息的名称,第二个参数为传入的参数。
(2.4)提供数据:pubsub.publish('getStudentName',this.student.name)
(2.5)容器销毁之前,取消消息订阅: pubsub.unsubscribe(this.pubId)
3.11 nextTick
(1)语法:this.$refs.inputTitle.focus()。
(2)作用:在下一次dom更新后在执行指定的回调函数。
(3)适用:数据改变后,基于更新后的dom执行某些操作时,在nextTick中指定回调函数。
3.12 过度与动画
(1)作用:在插入,更新,或者移除dom元素时,在合适的时候给元素添加样式类名。
(2):
(3)写法:
(3.1)准备好样式
元素进入:
.1)v-enter:进入的起点。
.2)v-enter-active:进入的过程中。
.3)v-enter-to:进入的重点。
元素移除入:
.1)v-leave:离开的起点。
.2)v-leave-active:离开的过程中。
.3)v-leave-to:离开的重点。
(3.2)使用<transition name='name'>包裹要过度的元素,并配置name属性。
(3.3)备注:若有多个元素使用transition,要用<transition-group>,且每个元素都要
指定key。
transition
<template> <div > <button @click="isShow=!isShow">显示/隐藏</button> <transition name="test" appear> <h1 v-show="isShow" class="test">显示/隐藏动画测试</h1> </transition> </div> </template> <script> export default { name:'Test', components:{ }, props:{ }, data() { return { isShow:true, } }, computed:{ }, watch:{ }, created() { }, mounted() { }, methods: { } } </script> <style scoped> .test{ background-color: skyblue; } .v-enter-active{ animation: test 1s linear; } .v-leave-active{ animation: test 1s reverse; } .test{ background-color: skyblue; } .test-enter-active{ animation: test 0.5s linear; } .test-leave-active{ animation: test 0.5s reverse; } @keyframes test{ from{ transform: translateX(-100%); } to{ transform: translateX(0px); } } </style>
transition-group
<template> <div > <button @click="isShow=!isShow">显示/隐藏</button> <!-- <transition name="test" appear> <h1 v-show="isShow" class="test">显示/隐藏动画测试</h1> </transition> --> <transition-group name="test" appear> <h1 v-show="!isShow" key="1" class="test">显示/隐藏动画测试1</h1> <h1 v-show="isShow" key="2" kclass="test">显示/隐藏动画测试2</h1> </transition-group> </div> </template> <script> export default { name:'Test', components:{ }, props:{ }, data() { return { isShow:false, } }, computed:{ }, watch:{ }, created() { }, mounted() { }, methods: { } } </script> <style scoped> .test{ background-color: orange; } /* 进入的起点 .test-enter{ transform: translateX(-100%); } /* 进入的终点 .test-enter-to{ transform: translateX(0px); } 离开的起点 .test-leave{ transform: translateX(0); } 离开的终点 .test-leave-to{ transform: translateX(-100%); }*/ /*进入的起点 离开的终点 */ .test-enter,.test-leave-to{ transform: translateX(-100%); } /*过程中*/ .test-enter-active,.test-leave-active{ transition: 0.5s linear; } /* 进入的终点 离开的起点 */ .test-enter-to,.test-leave{ transform: translateX(0px); } </style>
transition 引入css
<template> <div > <button @click="isShow=!isShow">显示/隐藏</button> <!-- <transition name="test" appear> <h1 v-show="isShow" class="test">显示/隐藏动画测试</h1> </transition> --> <transition-group name="animate__animated animate__bounce" enter-active-class="animate__backInDown" leave-active-class="animate__bounceOutLeft" appear> <h1 v-show="isShow" key="1" class="test">显示/隐藏动画测试1</h1> </transition-group> </div> </template> <script> export default { name:'Test', components:{ }, props:{ }, data() { return { isShow:false, } }, computed:{ }, watch:{ }, created() { }, mounted() { }, methods: { } } </script> <style scoped> .test{ background-color: orange; transition: 0.5; } </style>