先设置一下淘宝镜像,在create项目前
npm config set registry https://registry.npm.taobao.org/
执行npm run serve 之后
执行main.js文件 该文件是整个项目的入口文件
import Vue from 'vue' //引入vue import App from './App.vue' //引入App组件,他是所有组件的父组件 Vue.config.productionTip = false //关闭vue的生产提示 new Vue({ render: h => h(App), }).$mount('#app')
assets文件夹中配置静态资源(图片,音频等)
components文件夹中写组件
创建html元素,解析组件模板
##vue的项目流程
就是通过main.js将App组件渲染到页面指定位置
main.js就是vue项目的入口文件,是将App组件渲染到index.html文件的预留区域
render函数是创建App.vue的模板
先访问main.js
访问App.vue ,再访问App.vue中的子组件
解析App.vue模板,并挂载到指定的容器中
只要有runtime就代表是运行版本的vue,不包含模板解析器,只能用render函数来解析模板
this.$nextTick(回调函数)
vue在解析模板时,不会立即更改,只有将代码执行一遍后统一重新解析
只有在DOM元素更新到页面之后才执行函数体内代码
this.$nextTick( () =>{ this.$refs.inputTitle.focus(); });
配置mixin.js文件,写一些共用的方法,数据
export const hunru = { methods: { showName() { alert(this.name) } } }
在需要用到的组件里引入mixin.js文件
import { hunru } from "../mixin";
1
且要在组件里配置mixins属性
mixins: [hunru],
==全局混合> vm和所有vc都会得到mixin.js中的方法
(1)将mixin.js引入到main.js中
(2)Vue.mixin(hunru)
为了增强vue,在插件里写一些方法和数据,在vm和vc中都可以使用
定义插件
创建一个插件的js文件
使用插件
1.在main.js中引入插件js文件
2.使用插件
Vue.use(插件名)
写在style标签里,为了使相同class名在不同组件中使用
<style scoped>
</style>
父组件里修改子组件的样式,在使用第三方组件库时,修改组件默认样式
/deep/ h5{}
1.浏览器通过localStorage和sessionStorage属性来实现本地储存
2.localStorage保存一些数据,关闭浏览器,再次打开是数据还在
3.sessionStorage存一些数据,随着浏览器的关闭而消失
添加一个数据
localStorage.setItem('msg','hello') sessionStorage.setItem('msg','hello')
都是以字符串形式储存,第一个是key,第二个是value
读取数据
localStorage.getItem('msg') //没有对应的value会返回NUll
删除某个数据
localStorage.removeItem('msg')
1
删除所有数据
localStorage.clear()
父向子传参,props
rops传过来的属性,会直接出现在vc实例上,所以可以在插值语法中直接使用
props是只读的,不能修改props的值
如果从父组件里传的参数是通过axios请求得来的,在created、mounted中无法得到该值,可以通过watch属性监听该props属性,将值存入data中。而且必须用watch的对象方式监听。
让组件接受外部传来的数据
(1)传递数据到组件
<Student name="郭彦孚" sex="男" :age="1" />
(2)接受数据
1.简单接收
props: ["name", "sex", "age"]
2.限制类型 限制必要性 指定默认值
props中的数据名不能和data中的数据名相同,props的优先级更高,会优先显示props中属性名的值
:age=“js表达式”
组件中先读取props中的数据
props中传过来的数据不能改变,如果要改变复制一份放入data中,且不能同名
props: ["name", "sex", "age"], data() { return { myAge: this.age, }; }, methods: { add() { this.myAge++; }, },
##自定义事件(子向父传值)
1.主要实现子向父组件进行数据传递
2.和click等内置事件一样(@click=“”),要在父组件中给子组件添加一个自定义事件,父组件会收到子组件传过来的值
也可以添加事件修饰符.once之类的
<School @getSchoolName="schoolName" /> methods: { schoolName(name) { console.log("我的学校是" + name); }, },
3.在子组件内用$emit(“自定义事件名”,要传的参数) 来使用该自定义事件
methods: { send() { this.$emit("getSchoolName", this.name); }, },
4.解绑自定义事件
解绑一个自定义事件
this.$off(“自定义事件”)
解绑多个自定义事件
this.$off([“自定义事件“,”自定义事件”])
解绑所有自定义事件
this.$off()
第二中方法:父组件先给子组件一个函数,子组件调用该函数进行传值
使用一个事件修饰符(.native)
vue会将写在组件中的事件都看做自定义事件,要想触发原生的事件,要加.native
<School @click.native="schoolName" />
##ref属性
就是id的替代者
(1)可以在组件标签和html标签中添加ref=“xxx”
(2)应用在html标签上时获取的是真实DOM元素,在组件中获取的是组件的实例对象vc,然后就可以调用该组件的方法和数据
(3)获取时this.$refs.xxx
ref可以加在组价标签里,得到这个组件的实例对象,实现父组件直接调用子组件的方法和数据,给子组件绑定事件
this.$ref.student.$on('自定义事件名',回调函数),这个要在mounted函数中执行
##全局事件总线
实现任意组件间的通信
数据发送方,调用 e m i t ( ′ 事件名 称 ′ , 要发送的数据 ) 数据接收方,调用 emit('事件名称',要发送的数据) 数据接收方,调用 emit(′事件名称′,要发送的数据)数据接收方,调用on(‘事件名称’,事件处理函数) 最后在beforeDestory()函数中解绑自定义事件
安装全局事件总线$bus
on,emit, o f f 属性只有在 v u e . p r o t o t y p e 上才有,而 v c , v m 都可以访问 v u e . p r o t o t y p e ,所以每个组件都可以获得 off属性只有在vue.prototype上才有,而vc,vm都可以访问vue.prototype,所以每个组件都可以获得 off属性只有在vue.prototype上才有,而vc,vm都可以访问vue.prototype,所以每个组件都可以获得on, e m i t , emit, emit,off属性,将 b u s 绑定在 v u e . p r o t o t y p e 上,每个组件都可以看见它,并且将 bus绑定在vue.prototype上,每个组件都可以看见它,并且将 bus绑定在vue.prototype上,每个组件都可以看见它,并且将bus配置为vm,即 b u s 也会拥有 bus也会拥有 bus也会拥有on, e m i t , emit, emit,off属性
new Vue({ render: h => h(App), beforeCreate() { Vue.prototype.$bus = this //this就是vm } }).$mount('#app')
使用事件总线
接受数据:A组件想接受数据,就在A组件中给$bus绑定自定义事件,事件的回调留在A组件
methods: { //改变done的值 checkTodos(id) { this.todos.forEach((todo) => { if (todo.id == id) todo.done = !todo.done; }); }, }, mounted() { this.$bus.$on("checkTodos", this.checkTodos); //第一个是事件名,第二个是要执行的回调函数,也可以直接写成箭头函数 this.$bus.$on('checkTodos',(val)=>{ this.todos = val }) }, beforeDestroy() { this.$bus.$off("checkTodos"); },
5. 提供数据 this.$bus.$emit("checkTodos", id);
一种任意组件间通信的方式
使用步骤:
1. 安装pubsub:``npm i pubsub-js`` 1. 在需要通信的组件中引入 ``import pubsub from 'pubsub-js'`` 1. 在接受数据的组件中订阅消息
mounted(){ this.pid = pubsub.subscribe('事件名',回调函数) //每一个订阅消息都会返回一个id,要在beforeDestory中取消订阅 }, beforeDestroy() { pubsub.unsubscribe(pid) },
提供数据的组件中发布消息 pubsub.publish('事件名',数据)
就是在复用组件时,对复用组件的html结构进行调整
默认插槽
在组件标签里添加html结构,该html结构会插入到该组件里的位置
//在引入top组件的文件里,在top标签里直接添加html结构 <Top> <p>hello,world</p> </Top> //top组件中,在想插入的位置摆放<slot>标签 <template> <div> <slot></slot> </div> </template>
具名插槽
每个slot标签都有name属性 <slot name='left'></slot>
组件标签里加的元素要加上slot="left"
<Left> <template v-slot:left> //v-solt:指定插槽,只有在template中 v-slot:简写为# <p>hello</p> </template> </Left> <Top> <p slot="left">hello,world</p> <p slot="left">hhhh</p> </Top> //left组件 <div> <slot name="left"> </slot> //可以直接在slot标签中写内容,称为后备内容,当组件没有传内容时,默认显示 </div>
作用域插槽
还可以传值 父组件直接可以获得子组件传的值
数据在子组件,结构由父组件决定
//app组件 <Left> <template v-solt:header='params'> <p>{{ scope.params }}</p> //hello </template> </Left> //left组件 <div> <slotname:'header' msg="hello"></slot> </div>
//在方法形参()之前,不需要空格
“space-before-function-paren”:[“error”,“never”]
在vue.config.js中进行配置
module.exports = { devServer: { proxy: { '/api': { //匹配所有以api开头的路径 target: '<url>', //代理目标的基本路径 pathRewrite: { '^/api': '' }, //修改传回服务器的路径 ws: true, changeOrigin: true }, '/foo': { target: '<other_url>' } } } }
安装axios
npm i axios -S
引入axios
import axios from ‘axios’
axios.defaults.baseURL = ‘http://www.baidu.com’ //全局配置默认请求根路径
Vue.prototype.$http = axios
axios的返回值是promise实例对象,用await和async进行修饰和简化
vuex中一般存储组件之间共享的数据,适用于多组件共享某些数据,将这些共享的数据集中起来管理
vuex中数据都是响应式的,能够保持数据与页面的同步,数据改变重新解析模板
是实现集中式状态管理的一个Vue插件,适用于任意组件间通信
搭建vuex环境
安装vuex
npm i vuex
安装的是vuex4版本,该版本只能用在vue3,vue2只能用vuex3版本 npm i vuex@3
(1)创建store文件:src/store/index.js (先要有vuex,再创建store实例)
tore实例对象是由Vuex.store({})构造出来的,构造之后,在vc,vm上就会出现$store属性
$store属性中 有dispatch,commit方法
//引入vue import Vue from 'vue' //引入vuex import Vuex from 'vuex' Vue.use(Vuex) //用于响应组件中的动作 const actions = {} //用于储存数据 const state = {} //用于操作数据 const mutations = {} //创建并导出store export default new Vuex.Store({ actions, mutations, state })
(2)在main.js中引入store
//引入store import store from './store' //创建vm new Vue({ render: h => h(App), store, beforeCreate() { Vue.prototype.$bus = this } }).$mount('#app')
基本使用
1.在组件中使用dispatch给actions
this.$store.dispatch("jia", this.n);
2.在store中配置actions,actions主要写业务逻辑,将数据commit给mutations进行操作
如果没有网络请求或业务逻辑,可以直接越过actions,直接编写commit
const actions = { //context上下文,有commit,dispatch,state属性 jia(context, value) { context.commit('JIA', value) }, jian(context, value) { if(context.state.sum % 2){ context.commmit('JIA',value) } } }
3.mutations主要进行数据加工
mutations会收到两个参数,第一个是state,第二个就是传递过来的数据
const mutations = { JIA(state, value) { state.sum += value; }, JIAN(state, value) { state.sum -= value; } }
4.state 就是将一些共享的数据存放进来,类似与组件中的data
在组件模板中想使用state中数据
$store.state.sum
//用于储存数据 const state = { sum: 0 }
5.getters 就是将state中的数据进行运算加工,类似与组件中的computed
在组件中读取
$store.getters.bigData
const getters = { bigData(state){ return state.sum*10 //必须要用return语句,收到的参数就是state } }
6.mapState帮助程序猿简化代码,优化computed计算属性
首先要在组件中引入mapState
import {mapState} from 'vuex'
computed: { //借助mapState生成计算属性,从state中读取sum,并且形成sum函数 ...mapState(["sum"]),//==>sum(){ //return this.$store.state.sum } },
7.mapActions,模板中调用的函数要传参increment(n)
帮我们生成与actions对话的方法,即this.$store.dispatch("jia", this.n);
methods: { // increment() { // this.$store.dispatch("jia", this.n); // }, ...mapActions({ increment: "jia" }), },
mapActions使用时若需要传参,则要在模板绑定事件时传递参数,否则参数是事件对象
<button @click="increment(n)">+</button>1
mapMutations,模板中调用的函数要传参increment(n)
methods: { // increment() { // this.$store.commit("jia", this.n); // }, ...mapMutations({ increment: "jia" }), },
vuex模块化
让代码更好维护,让数据分类更加明确
(1)修改store.js
// count相关配置 const countOptions = { namespaced:true, //开启命名空间,mapState,mapActions等才能识别是哪个配置中的state,actions等 actions:{ addOdd(context,value){ if(context.state.sum % 2){ context.commit('ADDODD',value); } } }, mutations:{ ADD(state,value){ state.sum += value; }, DECREASE(state,value){ state.sum -= value; }, ADDODD(state,value){ state.sum += value; } }, state:{ sum:0, }, getters:{ } } //person相关配置 const personOptions = { namespaced:true, actions:{ }, mutations:{ ADDPERSON(state,value){ console.log(value); state.personList.unshift(value) } }, state:{ personList:[{id:'000',name:'李四'}] }, getters:{ length(state){ return state.personList.length } } } //导出时要加modules:{} export default new Vuex.Store({ modules:{ countAbout:countOptions, personAbout:personOptions } })
(2)组件读取数据
读state中数据
//直接读取 this.$store.state.count.sum //借助mapState ...mapState('countAbout',['sum'])
组件中调用commit,dispatch,getters的方式都类似
//直接读取 this.$store.commit('countAbout/ADD',person) //借助mapState ...mapMutations('countAbout',{add:'ADD'})