一.用户名显示和修改
1.显示用户名
基于2的笔记,我们在导航的同级,显示用户名,用户名来自data的设置:
App.vue:
tab切换显示:
my-component you-component love-component - 用户名:{ {username}}
显示效果:
我们在myComponent组件的子组件mySet组件会显示用户名,并且可以修改他,然后导航位置和mySet都会显示为最新的。
利用属性:App.vue:
tab切换显示:
my-component you-component love-component - 用户名:{ {username}}
我们先把这个用户名传递给myComponent组件:
myComponent.vue:
{ {info}} { {username}}
我们预览效果:
mySet组件创建,并且显示这个用户名:
mySet.vue:
用户名{ {username}}
myComponent.vue调用组件和属性传递:
{ {info}}
main.js注册这个组件:
import Vue from 'vue'import App from './App.vue'import VueRouter from 'vue-router'import myComponent from './myComponent.vue'import youComponent from './youComponent.vue'import loveComponent from './loveComponent.vue'import myDetail from './myDetail.vue'import lovePhone from './lovePhone.vue'import loveInfo from './loveInfo.vue'import loveAddress from './loveAddress.vue'import mySet from './mySet.vue'//注册组件Vue.component('my-set', mySet)//路由配置Vue.use(VueRouter); var routes = [ { path: '/', component: myComponent}, { path: '/youComponent', component: youComponent}, { path: '/loveComponent', component: loveComponent, redirect: '/loveComponent/lovePhone', children: [ { path: 'lovePhone', component: lovePhone }, { path: 'loveInfo', component: loveInfo }, { path: 'loveAddress', component: loveAddress } ] }, { path: '/myDetail/:id', component: myDetail}]var router = new VueRouter({ routes: routes // (缩写)相当于 routes: routes})router.beforeEach(function (to, from, next){ console.log(to,"即将要进入的目标 路由对象"); console.log(from,"当前导航正要离开的路由"); next(); })var app = new Vue({ router, render:h=>h(App)}).$mount("#app")
显示效果:
经过两次属性传递,我们在mySet组件获取和显示成功!
2.修改用户名
我们把工作回到mySet组件,我们加一个输入框显示这个名字,然后加一个按钮,确定修改:
用户名{ {username}}
显示如下:
我们输入框修改用户名,点击确认修改,那么就会把App.vue的username修改为输入的值,这样显示的2处显示就自动更新为最新的了,利用v-mode可以双向绑定数据,所以alert就是输入框的内容。
我们使用$emit处理:
mySet.vue:
用户名{ {username}}
myComponent.vue定义激发的事件和调用对应函数获取修改值:
{ {info}}
App.vue定义激发事件和获取参数,这里设置用户名为mySet传上来的值:
tab切换显示:
my-component you-component love-component - 用户名:{ {username}}
效果测试:
二.组件交互开发总结
当然上面只是一个演示的例子,我们的项目中其实有很大可能出现这种处理,或者更复杂的处理,也许有10级嵌套。所以我们希望出现一个这样的处理方式,对于显示的值:
架设我们的大容器叫做 store, 架设store.name存放了小李子。
然后在header组件我们可以直接获取store.name 然后显示处理,假如this.store.name就拿到了。
同理在setname组件同理使用,然后这个组件修改之后就是修改store.name为新名字。
然后使用这个store.name位置监听变化会自动重新渲染。
vue开发中就有这么一个框架,那就是vuex,他会帮助我们解决这样的问题。
三.使用vuex
1.安装vuex
同vue-router的使用,支持两种方式安装:
package.json:
{ "name": "y", "description": "后台项目", "version": "1.0.0", "author": "tbd", "private": true, "scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, "dependencies": { "vue": "^2.3.3" }, "devDependencies": { "babel-core": "^6.0.0", "babel-loader": "^6.0.0", "babel-preset-env": "^1.5.1", "cross-env": "^3.0.0", "css-loader": "^0.25.0", "file-loader": "^0.9.0", "vue-loader": "^12.1.0", "vue-template-compiler": "^2.3.3", "webpack": "^2.6.1", "webpack-dev-server": "^2.4.5", "vue-router": "^*", "vuex": "^*" }}
执行:
npm install
npm手动
npm install vuex
2.配置vuex
创建vuex的状态树,这个非常简单,我们创建store.js,这是有规定的,就是state属性存放我们的状态值,就如组件data属性一样:
store.js:
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)var store = new Vuex.Store({ state: { username: "小刚" }})export default store
3.引用vuex
这样我们把状态树就引用到所有组件当中了,我们组件中通过this.$store.state就可以拿到和使用
4.使用vuex
this.$store在组件中拿到这个状态树,需要什么我们就显示什么,如:this.$store.state.xx:
App.vue:
tab切换显示:
my-component you-component love-component - 用户名:{ {username}}
mySet.vue:
用户名{ {username}}
显示效果:
我们2个位置的显示不需要在使用属性进行传递了,把这个公用的状态值存在了vuex中。
四.修改vuex状态值
1.mutations定义和commit触发
我们已经获取了store中的状态值,现在我们在mySet组件点击按钮修改他,因为vuex提供了对store中state修改的功能,
store.js加入修改state的处理函数:
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)var store = new Vuex.Store({ state: { username: "小刚" }, mutations: { setusername (state,newusername) { // 变更状态 state.username=newusername } }})export default store
在mutations属性配置修改state的方法,方法的第一个接受值就是本身的state对象,后面的参数是接收的额外传递参数,然后修改对应状态即可!
在调用位置,我们在new vue实例中把store应用到了全局,我们在组件中通过this.$store.commit触发,调用mutations属性配置的方法,commit第一个参数就是指定触发哪一个方法,后面是传入的额外参数。
mySet.vue:
用户名{ {username}}
这是对比图:
浏览器查看效果:
在这个使用中,官方有这样的介绍,必须是同步函数:
2.Action定义和dispatch触发
这个和上面是使用非常相似,Action属性定义的方法可以触发mutations属性定义的方法,通过commit。
我们修改store.js,写一个Action,然后触发commit去调用mutations:
在action的context对象包含commit方法和state对象等,也就可以拿到对应状态。
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)var store = new Vuex.Store({ state: { username: "小刚" }, mutations: { setusername (state,newusername) { // 变更状态 state.username=newusername } }, actions: { setusername (context,newusername) { context.commit('setusername',newusername) } }})export default store
mySet.vue去调用:
用户名{ {username}}
流程截图:
action可以包含任何异步操作,也就是支持任意操作:
this.$store.dispatch返回 Promise ,在调用位置使用then:
而一般的异步处理是这样的,我们的参数一般是一个url然后在action调用ajax,在ajax的成功或者失败中出发commit修改对应状态。
3.Getter
这个就是如同组件中computed计算属性的使用。实际的功能就是我们现在除了要显示名字,还要显示名字的长度,我们就可以利用Getter的处理,变得非常简单:
store.js:
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)var store = new Vuex.Store({ state: { username: "小刚" }, getters:{ usernamelen:function(state){ return state.username.length } }, mutations: { setusername (state,newusername) { // 变更状态 state.username=newusername } }, actions: { setusername (context,newusername) { context.commit('setusername',newusername) } }})export default store
如同计算属性的使用,我们在这个属性的方法中会接收到state,在一定逻辑处理之后,return返回对应值。
在应用位置和state的使用很相似,只是this.$store.state.xx和this.$store. getters .xx的区别:
App.vue:
tab切换显示:
my-component you-component love-component - 用户名:{ {username}}长度:{ {usernamelen}}
mySet.vue:
用户名{ {username}}长度:{ {usernamelen}}
浏览器测试:
五.Module使用
为什么要使用模块呢,其实很简单,如果我们的页面有新闻页面和商品页面,都存在列表,我们可能就想简写存在list状态中,为了业务的清晰,使用模块真的非常重要。
一般在store根位置我们会存一些全局的状态,其他对应页面等的都会存在对应的位置,这个标记就是我们Module的名字:
因为有了module的设置,在获取属性时就有了一个前缀(模块名称)的区分。