vue笔记
使用淘宝镜像
- 地址:http://npm.taobao.org/
- 安装cnpm:
shell npm install -g cnpm --registry=https://registry.npm.taobao.org
搭建vue的开发环境:
- 必须要安装nodejs
- 搭建vue的开发环境 ,安装vue的脚手架工具 官方命令行工具
npm install --global vue-cli / cnpm install --global vue-cli (此命令只需要执行一次)
- 创建项目 必须cd到对应的一个项目里面
vue init webpack vue-demo01 cd vue-demo01 cnpm install / npm install 如果创建项目的时候没有报错,这一步可以省略。如果报错了 cd到项目里面运行 cnpm install / npm install npm run dev
- 另一种创建项目的方式 (推荐) ***
``` shell
vue init webpack-simple vuedemo02
cd vuedemo02
cnpm install / npm install
npm run dev
现在开始创建一个.vue文件,在src下创建MyApp.vue
<template>
<div id="myapp">
<img src="./assets/logo.png" alt="">
<h1>{{msg}}</h1>
<h3>{{obj.name}}</h3>
<hr>
<ul>
<li v-for="item in lists">{{item}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "MyApp",
data() {
return {
msg: 'welcome to myapp',
obj:{
name:'张三'
},
lists:['1','2','A','B']
}
}
}
</script>
<style scoped>
</style>
修改main.js
import Vue from 'vue'
import MyApp from './MyApp'
new Vue({
el: '#app',
render: h => h(MyApp)
})
添加删除小案例
<template>
<div id="myapp">
+add:<input v-model="todo" @keydown="addList($event)">
<h3>正在进行</h3>
<ul>
<li v-for="(v,k) in lists3" v-if="!v.checked">
<input type="checkbox" v-model="v.checked"> {{v.title}} <button @click="delV(k)">-del</button>
</li>
</ul>
<hr>
<h3>完成</h3>
<ul>
<li v-for="(v,k) in lists3" v-if="v.checked">
<input type="checkbox" v-model="v.checked"> {{v.title}} <button @click="delV(k)">-del</button>
</li>
</ul>
<hr>
</div>
</template>
<script>
export default {
name: "MyApp",
data() {
return {
todo:'',
lists3:[],
}
},
methods:{
addList(e){
if (e.keyCode===13){
this.lists3.push({
title:this.todo,
checked:false
});
this.todo = '';
}
},
delV(key){
this.lists3.splice(key,1)//删除lists3的第key个,删除一个
},
}
}
</script>
<style scoped>
</style>
刷新数据会丢失,接下来我们保存到本地浏览器中
<template>
<div id="myapp">
+add:<input v-model="todo" @keydown="addList($event)">
<h3>正在进行</h3>
<ul>
<li v-for="(v,k) in lists3" v-if="!v.checked">
<input type="checkbox" v-model="v.checked" @change="addLocalStorage()"> {{v.title}} <button @click="delV(k)">-del</button>
</li>
</ul>
<hr>
<h3>完成</h3>
<ul>
<li v-for="(v,k) in lists3" v-if="v.checked">
<input type="checkbox" v-model="v.checked" @change="addLocalStorage()"> {{v.title}} <button @click="delV(k)">-del</button>
</li>
</ul>
<hr>
</div>
</template>
<script>
export default {
name: "MyApp",
data() {
return {
todo:'',
lists3:[],
}
},
methods:{
addList(e){
if (e.keyCode===13){
this.lists3.push({
title:this.todo,
checked:false
});
this.todo = '';
this.addLocalStorage()
}
},
delV(key){
this.lists3.splice(key,1)//删除lists3的第key个,删除一个
this.addLocalStorage()
},
addLocalStorage(){
localStorage.setItem('list',JSON.stringify(this.lists3))
}
},
mounted() {//vue页面刷新就会执行的方法
var list = JSON.parse(localStorage.getItem('list'));
if(list){
this.lists3 = list;
}
}
}
</script>
<style scoped>
</style>
接下来考虑对localStorage操作进行封装:
storage.js:
// localStorage的操作封装
// src/model/storage.js
var storage = {
set(key,value){
localStorage.setItem(key,JSON.stringify(value))
},
get(key){
return JSON.parse(localStorage.getItem(key))
},
remove(key){
localStorage.removeItem(key)
}
};
export default storage
引入storage
<script>
import storage from './model/storage'
export default {
name: "MyApp",
data() {
return {
todo:'',
lists3:[],
}
},
methods:{
addList(e){
if (e.keyCode===13){
this.lists3.push({
title:this.todo,
checked:false
});
this.todo = '';
this.addLocalStorage()
}
},
delV(key){
this.lists3.splice(key,1)//删除lists3的第key个,删除一个
this.addLocalStorage()
},
addLocalStorage(){
storage.set('list',this.lists3);
}
},
mounted() {//vue页面刷新就会执行的方法
var list = storage.get('list');
if(list){
this.lists3 = list;
}
}
}
</script>
组件的使用
Home.vue
```html
home组件
引入组件
```html
<template>
<div id="myapp">
<v-home></v-home>
</div>
</template>
<script>
import home from './components/Home'
export default {
name: "MyApp",
components:{
'v-home':home
}
}
</script>
<style scoped>
/*scoped 局部作用域*/
</style>
生命周期实例
<template>
<div>
<h3>home组件</h3>
</div>
</template>
<script>
export default {
name: "home",
beforeCreate() {
console.log('实例刚刚被创建1')
},
created() {
console.log('实例已经创建完成2')
},
beforeMount() {
console.log('模板编译之前3')
},
mounted() { //请求数据,操作dom可在这进行
console.log('模板编译完成4')
},
beforeUpdate() {
console.log('数据更新之前')
},
updated() {
console.log('数据更新完毕')
},
beforeDestroy() {//页面销毁前报错数据
console.log('实例销毁之前')
},
destroyed() {
console.log('实例销毁完成')
}
}
</script>
<style scoped>
</style>
<template>
<div id="myapp">
<v-home v-if="flag"></v-home>
{{msg}}
<button @click="changeMsg()">change</button>
<br>
<button @click="flag=!flag">挂载组件/销毁组件</button>
</div>
</template>
<script>
import home from './components/Home'
export default {
name: "MyApp",
data(){
return{
msg:'改变之前',
flag:false
}
},
methods:{
changeMsg(){
this.msg = '改变之后'
}
},
components:{
'v-home':home
},
beforeCreate() {
console.log('实例刚刚被创建1')
},
created() {
console.log('实例已经创建完成2')
},
beforeMount() {
console.log('模板编译之前3')
},
mounted() { //请求数据,操作dom可在这进行
console.log('模板编译完成4')
},
beforeUpdate() {
console.log('数据更新之前')
},
updated() {
console.log('数据更新完毕')
},
beforeDestroy() {//页面销毁前报错数据
console.log('实例销毁之前')
},
destroyed() {
console.log('实例销毁完成')
}
}
</script>
<style scoped>
/*scoped 局部作用域*/
</style>
初始化项目
vue init webpack vue-demo
ESLint ? N 是否需要 js 语法检测
进入 cd vue-demo
执行
npm install
接下来执行
npm run dev
,默认浏览器会自动打开
打包发布:
npm run build
npm install -g serve
serve dist
基础指令:
{{}}
v-one: 只渲染一次
v-html:解析HTML结构
v-bind: => 简写 :
v-if :是惰性的
v-else
v-show:是否显示或隐藏,只是通过操作css
v-for (k,i) (v,k,i) :key
v-on: => 简写 @
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
变异数组:
push()
pop()
shift()
unshift()
前splice()
sort()
reverse()
- concat 数组合并
数组调用变异方法:example1.items.push({ message: 'Baz' })
。
替换数组:
例如:filter()
, concat()
和 slice()
。这些不会改变原始数组,但总是返回一个新数组。
components: 组件
computed() 计算属性
methods: 方法
Class与Style绑定 class="[{}]" 对象中可以接受字符串,数组中接受对象
data: data函数,初始化数据 data中的a,b,c 获取常用方法: const{ a,b,c} = this
props:[] 通过 Prop 向子组件传递数据
调用内建的 [**\(emit** 方法]并传入事件的名字,来向父级组件触发一个事件:
使用 `\)emit` 的第二个参数来提供这个值:
<template>
<div>
父组件: {{mon}} <!--子传父-->
<child @money="getMoney" title="一个小目标"/>
</div>
</template>
<script>
import child from './child'
export default {
name: "parent",
data() {
return {
mon: "",
}
},
components: {
child,
},
methods: {
getMoney(data) { // 子传父
this.mon = data;
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
子组件:
{{title}} <!--父传子-->
<button @click="sendMoney">点击</button> <!--子传父-->
</div>
</template>
<script>
export default {
name: "child",
data() {
return {}
},
props: ["title"],//父传子
methods: {
sendMoney() { //子传父
this.$emit("money", "先整一个亿?")
}
}
}
</script>
<style scoped>
</style>
类型:
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object
}
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
加载组件
<component v-bind:is="currentTabComponent"></component>
keep-alive
<!-- 失活的组件将会被缓存!-->
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
访问根实例:
在每个 new Vue
实例的子组件中,其根实例可以通过 $root
属性进行访问。例如,在这个根实例中:
// Vue 根实例
new Vue({
data: {
foo: 1
},
computed: {
bar: function () { /* ... */ }
},
methods: {
baz: function () { /* ... */ }
}
})
所有的子组件都可以将这个实例作为一个全局 store 来访问或使用。
// 获取根组件的数据
this.$root.foo
// 写入根组件的数据
this.$root.foo = 2
// 访问根组件的计算属性
this.$root.bar
// 调用根组件的方法
this.$root.baz()
访问子组件实例或子元素:
<base-input ref="usernameInput"></base-input>
this.$refs.usernameInput
插槽:
<模板1>
you profile
</模板1>
在模板1的
1.基础插槽 自定义指令: 如果想注册局部指令,组件中也接受一个 然后你可以在模板中任何元素上使用新的 过滤器: 你可以在一个组件的选项中定义本地的过滤器: axios: 一个中文网站: https://www.kancloud.cn/yunye/axios/ 执行 执行 这里的参数如果是?name=""&age=11 转为{name:"",age:11} 可使用ps转换 import ps from 'ps' ps.stringify({.....}) 在请求或响应被 axios封装: 使用: 通过代理解决跨域:** 配置config/index.js main.js: 注意重启服务器 Vue Router 安装 提取到router main.js 路由跳转: 路由带参数: HelloWorld.vue中: 嵌套路由: 编程式导航: push: router.replace 不会向 history 添加新记录 go 命名路由: 重定向: 路由对象属性: vue-router的理解和使用 $route.path 类型: 字符串,对应当前路由的路径,总是解析为绝对路径 类型: 默认值: 全局配置 类型: 默认值: 全局配置 路由高亮: linkActiveClass的样式设置 回退: 其他方式:如过路由匹配,就指定样式 meta: 路由隐藏实例: Swiper 4.0: 目前应用较广泛的移动端网页触摸内容滑动js插件 https://www.swiper.com.cn/usage/index.html 1.首先加载插件,需要用到的文件有swiper.min.js和swiper.min.css文件。可下载Swiper文件或使用CDN。 2.HTML内容。 3.你可能想要给Swiper定义一个大小,当然不要也行。 4.初始化Swiper:最好是挨着标签 如果不能写在HTML内容的后面,则需要在页面加载完成后再初始化。 或者这样(Jquery和Zepto)(推荐) 5.完成。恭喜你,现在你的Swiper应该已经能正常切换了。 其他: 其他: Element:** 组件库,饿了么出品 https://element.faas.ele.me/#/zh-CN iview: UI 组件库 下拉刷新: npm install --save pull-to-refresh stylus: .styl格式 css预编译器 其他(less , sass) 编写: 结构通过缩进,不需要大括号分号,冒号随便 父级引用: 使用&指向父选择器: 通过@import引入其他样式文件 min 实例: 使用: VUEX vuex main.js 使用 actions: 异步获取数据到 使用 actions 2:mapActions 取state中的数据: 简单的正则: 倒计时: 注意 ` 符号 event.target:
2.具名插槽
3.编译作用域
父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。
4.作用域插槽(数据传递)
在 2.5.0+,slot-scope 不再限制在 元素上使用,而可以用在插槽内的任何元素或组件上。
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
directives
的选项:directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
v-focus
属性,如下:<input v-focus>
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
cnpm install --save axios
import Axios from 'axios'
Vue.prototype.$axios = Axios
GET
请求// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 可选地,上面的请求可以这样做
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
POST
请求axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
全局的 axios 默认值
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
拦截器
then
或 catch
处理前拦截它们。// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
if(config.method==='post'){
config.data = qs.stringify(config.data)
}
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
//ajax 请求函数
import axios from 'axios'
export default function ajax(url, data = {}, type = 'GET') {
return new Promise(function (resolve, reject) {
// 执行异步ajax请求
let promise
if (type === 'GET') {
// 准备url query参数数据
let dataStr = '' //数据拼接字符串
Object.keys(data).forEach(key => {
dataStr += key + '=' + data[key] + '&'
})
if (dataStr !== '') {
dataStr = dataStr.substring(0, dataStr.lastIndexOf('&'))
url = url + '?' + dataStr
}
// 发送get请求
promise = axios.get(url)
} else {
// 发送post请求
promise = axios.post(url, data)
}
promise.then(function (response) {
// 成功了调用resolve()
resolve(response.data)
}).catch(function (error) {
//失败了调用reject()
reject(error)
})
})
}
import ajax from './ajax'
// 参数param
export const reqAddress = geohash => ajax('/api/position/'+geohash)
// 无参数
export const reqFoodTypes = () => ajax('/index_category')
// 参数query 即? latitude:latitude :后的要与()参数一致
export const reqShops = (longitude,latitude) => ajax('/shops',{longitude:longitude,latitude:latitude})
//post 请求体
export const reqSmsLogin = (phone,code) => ajax('/login_sms',{phone,code},'POST')
proxyTable: {
'/doubai_api':{ //匹配所有/doubai_api开头的请求路径
target: 'http://api.douban.com',
pathRewrite: { //重写路径,去掉开头的/doubai_api
'^/doubai_api': ''
},
changeOrigin: true //支持跨域
}
},
Vue.prototype.HOST = "/doubai_api"
访问:
var url = this.HOST + "/v2/movie/top250";
this.$axios({
method: 'get',
url: url
})
.then(res => {
console.log(res.data);
})
.catch(error => {
console.log(error);
})
cnpm install vue-router --save
import VueRouter from 'vue-router'
import HelloWorld from "@/components/HelloWorld"
Vue.use(VueRouter)
const router = new VueRouter({
routes:[
{
path:'/hello',
name:'HelloWorld',
component:HelloWorld
}
]
})
new Vue({
el: '#app',
router,
data:{haha:'123'},
components: { App },
template: '<App/>'
})
<router-view/>
import Vue from 'vue'
import VueRouter from 'vue-router'
import HelloWorld from "@/components/HelloWorld.vue"
Vue.use(VueRouter)
export default new VueRouter({
routes:[
{
path:'/',
name:'HelloWorld',//作为跳转使用
component:HelloWorld
}
]
})
import router from '@/router'
new Vue({
el: '#app',
router,
data:{haha:'123'},
components: { App },
template: '<App/>'
})
<!--tag 渲染为li-->
<router-link tag="li" to="/hello">HelloWorld</router-link>
<router-link tag="li" to="/">首页</router-link>
path:'/hello/:id', //传参
<!--tag 渲染为li-->
<router-link tag="li" to="/hello/hahaha">HelloWorld</router-link>
<h2 v-text="this.$route.params.id"></h2>
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts
}
]
}
]
})
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// path:'/hello/:id', //传参
path:'/hello/', //传参
<router-link tag="li" :to="{name:'HelloWorld',params:{id:params_id}}">HelloWorld</router-link>
data(){
return{
params_id:'abc'
}
},
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' }
]
})
router-view/router-link/keep-alive
$router: 路由器对象, 包含一些操作路由的功能函数, 来实现编程式导航(跳转路由)
$route: 当前路由对象, 一些当前路由信息数据的容器, path/meta/query/params
string
export default new VueRouter({
/*class换个名字*/
linkActiveClass:"active",/*全局配置 <router-link> 的默认“激活 class 类名”*/
linkExactActiveClass:"currentActive",/*全局配置 <router-link> 精确激活的默认的 class*/
routes:[
linkActiveClass
string
"router-link-active"
<router-link>
的默认“激活 class 类名”linkExactActiveClass
string
"router-link-exact-active"
<router-link>
精确激活的默认的 class.active{
color: red;
}
@click="$route.back()"
:class="{on: '/msite'===$route.path}"
{
path: '/msite',
component:Msite,
meta:{
showFooter: true
}
},
v-show="$route.meta.showFooter"
npm install --save swiper
import Swiper from 'swiper'
import 'swiper/dist/css/swiper.min.css'
// 或
cnpm install --save vue-awesome-swiper
Swiper4.x使用方法
<!DOCTYPE html>
<html>
<head>
...
<link rel="stylesheet" href="dist/css/swiper.min.css">
</head>
<body>
...
<script src="dist/js/swiper.min.js"></script>
...
</body>
</html>
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
<!-- 如果需要导航按钮 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- 如果需要滚动条 -->
<div class="swiper-scrollbar"></div>
</div>
导航等组件可以放在container之外
.swiper-container {
width: 600px;
height: 300px;
}
...
<script>
var mySwiper = new Swiper ('.swiper-container', {
direction: 'vertical', // 垂直切换选项
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// 如果需要滚动条
scrollbar: {
el: '.swiper-scrollbar',
},
})
</script>
</body>
<script>
window.onload = function() {
...
}
</script>
<script>
$(document).ready(function () {
...
})
</script>
<script>
//局部使用
import 'swiper/dist/css/swiper.css'
import {swiper, swiperSlide} from 'vue-awesome-swiper'
export default {
name: "Swiper_Banner",
components: {
swiper,
swiperSlide
}
}
</script>
watch: {
// 监控 categorys变化
categorys(value) {
// setTimeout(() => {
// new Swiper('.swiper-container', {
// loop: true, // 循环模式选项
// // 如果需要分页器
// pagination: {
// el: '.swiper-pagination',
// }
// })
// }, 100)
//将回调延迟下次DOM更新循环之后执行
//界面更新立即创建swiper对象
this.$nextTick(()=>{
new Swiper('.swiper-container', {
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
}
})
})
}
},
npm install --save pull-to-refresh
npm install stylus stylus-loader --save-dev
<style lang="stylus" rel="stylesheet/stylus">
.app
color red
</style>
text:hover{
}
// 等同于
text
&hover
$green = #02a774;
$yellow = #F5A100;
$bc = #e4e4e4;
// 一像素下边框
bottom-border-1px($color)
position relative
border none
&:after
content ''
position absolute
left 0
bottom 0
width 100%
height 1px
background-color $color
transform scaleY(0.5)
// 一像素上边框
top-border-1px($color)
position relative
&::before
content ''
position absolute
z-index 200
left 0
top 0
width 100%
height 1px
background-color $color
//根据像素比缩放 1px 像素边框
@media only screen and (-webkit-device-pixel-ratio: 2 )
.border-1px
&::before
transform scaleY(.5)
@media only screen and (-webkit-device-pixel-ratio: 3 )
.border-1px
&::before
transform scaleY(.333333)
//根据像素比来使用 2x 图 3x 图
bg-image($url)
background-image: url($url + "@2x.png")
@media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
background-image: url($url + "@3x.png")
//清除浮动
clearFix()
*zoom 1
&::after
content ''
display block
clear both
@import "../../common/stylus/mixins.styl"
.footer_guide //footer
top-border-1px(#e4e4e4)
npm install --save vuex
/*核心管理对象*/
import Vue from 'vue'
import Vuex from 'vuex'
/*状态对象*/
import state from './state'
/*直接更新state的多个方法对象*/
import mutations from './mutations'
/*通过mutation间接更新sate的多个方法对象*/
import actions from './actions'
/*包含基于state的getter计算属性的对象*/
import getters from './getters'
Vue.use(Vuex)
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
/*状态对象*/
export default {
latitude: 40.10038,//纬度
longitude: 116.36867,//经度
address: {},//地址信息对象
categorys: [],//分类数组
shops: [],//商家数组
}
/*包含n个mutation的type名称常量*/
export const RECEIVE_ADDRESS = 'receive_address' //接收地址信息
export const RECEIVE_CATEGORYS = 'receive_categorys' //接收分类数组
export const RECEIVE_SHOPS = 'receive_shops' //接收商家数组
/*直接更新state的多个方法对象*/
import {
RECEIVE_ADDRESS,
RECEIVE_CATEGORYS,
RECEIVE_SHOPS
} from './mutation-types'
export default {
[RECEIVE_ADDRESS](state, {address}) {
state.address = address
},
[RECEIVE_CATEGORYS](state, {categorys}) {
state.categorys = categorys
},
[RECEIVE_SHOPS](state, {shops}) {
state.shops = shops
},
}
/*通过mutation间接更新sate的多个方法对象*/
import {
RECEIVE_ADDRESS,
RECEIVE_CATEGORYS,
RECEIVE_SHOPS
} from './mutation-types'
import {
reqAddress,
reqFoodCategorys,
reqShops,
} from '../api'
export default {
//异步获取地址
async getAddress({commit, state}) {
const geohash = state.latitude + ',' + state.longitude
const result = await reqAddress(geohash)
if (result.code === 0) {
const address = result.data
commit(RECEIVE_ADDRESS, {address})
}
},
async getCategorys({commit}) {
const result = await reqFoodCategorys()
if (result.code === 0) {
const categorys = result.data
commit(RECEIVE_CATEGORYS, {categorys})
}
},
async getShops({commit, state}) {
const {longitude,latitude} = state
const result = await reqShops(longitude, latitude)
if (result.code === 0) {
const shops = result.data
commit(RECEIVE_SHOPS, {shops})
}
},
}
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
/* eslint-disable no-new */
new Vue({
el: '#app',
render:h=>h(App),
router,
store, //
})
created(){
this.$store.dispatch('getAddress')
}
import {mapActions} from 'vuex'
export default {
name: 'App',
methods:{
...mapActions(['getAddress'])
},
mounted(){
this.getAddress()
},
import {mapState} from 'vuex'
computed:{
rightPhone(){
return /^1\d{10}$/.test(this.phone)
}
}
{{computeTime>0 ? `已发送(${computeTime}s)`:'获取验证码'}}
methods:{
getCode(){
if (!this.computeTime){
this.computeTime = 30
const intervalId = setInterval(()=>{
this.computeTime--
if (this.computeTime<=0){
//停止计时
clearInterval(intervalId)
}
},1000)
}
}
}
//event.target返回的是点击的元素节点