一、新增页面
- 在src/pages下面新建文件夹,并且新建xxx.vue/main.js/main.json文件
- app.json文件新增页面路径
- ctrl+c退出 npm run dev重新编译
- xxx.vue页面结构
<template>
<div class="container">
// ... html 注意:template标签下只能有一个根元素 否则报错
</div>
</template>
<script>
export default{
data () {
return {
// ... 数据
}
},
methods: {
// ... 方法
}
}
</script>
<style lang="less">
// ... less 样式
</style>
或者
<style>
// ... 普通的css样式
</style>
- mpvue和mpvue-weui
mpvue是一个使用 Vue.js 开发小程序的前端框架。框架基于 Vue.js 核心,mpvue 修改了 Vue.js 的 runtime 和 compiler 实现,使其可以运行在小程序环境中,从而为小程序开发引入了整套 Vue.js 开发体验。
mpvue-weui是基于mpvue框架和小程序原生组件的基础样式库,可供快速开发。
【官网】https://kuangpf.com/mpvue-weui/
二、新增组件
- 在src/components下新建test.vue文件
- test.vue (与页面结构一致)
<template>
<div class="container">
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods: {
}
}
</script>
<style lang="less">
// ... 样式
</style>
- 使用组件
在xxx.vue页面上使用
<script>
// ① 导入组件
import myTest from "@/components/test";
export default {
// ② 声明组件
components: { myTest },
data () {
return {
// ...
}
},
}
</script>
<template>
<div class="container">
<!-- ③ 使用组件 -->
<my-test></my-test>
</div>
</template>
- 组件间的传值
① 父组件传值给子组件
父组件.vue
<my-test :result="resultMsg"></my-test>
// 使用:号绑定一个result属性名,传递的值为父组件的resultMsg
data () {
return {
resultMsg: '我是父组件传给子组件的值'
}
},
② 子组件接收父组件传递过来的值
子组件.vue
<template>
<div class="container">
<p>{{result}}</p> // ② 页面上使用 注:如果在vue对象中使用则为this.result
</div>
</template>
export default {
// ① 通过props接收信息
// 这里props引用的是父组件在子组件上绑定的属性名,它的值就是传递过来的值
props:['result'],
data () {
return {
// ...
}
},
}
- props的三种方式:
// 第一种:
props: ['result']
// 第二种:
props: {
result: String // 这里指定了字符串类型,如果类型不一致会警告的哦
}
// 第三种:
childCom: {
type: String, // 这里指定类型
default() {
return '' // 这里设置默认值,如果父组件未传入则使用默认值
}
}
③ 子组件向父组件传值
子组件.vue
// 给一个input绑定一个blur事件
<input type="text" v-model="inputValue" @blur="blurFn">
methods: {
data: function () {
return {
inputValue: ''
}
},
blurFn () {
this.$emit("changeValue", this.inputValue)
// 子组件发射自定义事件 testValue, 并且传递值 inputValue
// 如果要传递多个值,写法为 this.$emit("事件名", 值1,值2,值3)
}
}
④ 父组件接收子组件传递过来的值
父组件.vue
<my-test @changeValue="parentChangeValue"></my-test>
// 父组件在子组件上使用@事件名="方法名"接收,其中事件名是子组件$emit发射的事件名
methods: {
// 在方法里定义一个接收值的函数
parentChangeValue(value){
console.log(value); // 这里的value就是子组件传递过来的inputValue的值
}
}
三、模板语法
- for循环
<ul v-for="(item, index) in list">
<li v-for="(v, i) in item"> // 注:嵌套循环需指定不同的索引
{{v.value}}
</li>
</ul>
- 条件渲染
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
- 属性绑定与事件绑定
<a @click.stop="chooseHome">a标签</a>
// 用@事件名="函数名" 绑定事件 .stop是修饰符,阻止冒泡
<button :disabled="true"></button>
<img :src="item.deviceLogo">
// 用:属性名="变量名"绑定。注:布尔值也需要使用:号绑定,否则被视为字符串。
4.Class 与 Style 动态绑定
<p :class="{ 'active': isActive }">xxxxx</p>
// 'active' 类名 isActive 是否绑定的判断条件
<p :style="{ color: activeColor, fontSize: fontSize + 'px' }">xxxxx</p>
// 例: activeColor: '#ccc', fontSize: 24 转化后
<p style="color:'#ccc';font-size: 24px;">xxxxx</p>
四、常用demo
- 上拉加载、下拉刷新
// ① 导入组件
import xview from "@/components/xview";
// ② 声明组件
components: { xview,noDevices,msgModal,devModal },
// ③ 使用组件
<scroll-view class="facilist-view">
<xview @pulldownrefresh="pullDownRefresh" @scroll="scroll" @loadmore="loadmore" :refreshing="refreshing" :nomore="nomore" :hideLoadMore="hideLoadMore" ref="xview">
<ul>
<li></li>
</ul>
</xview>
</scroll-view>
// 注释:
// pulldownrefresh 下拉刷新监听函数 在这个方法里做刷新列表动作
// loadmore 上拉加载监听函数 在这个方法里做加载下一页动作
// scroll 滚动事件 不做处理
// hideLoadMore 是否在加载完后隐藏上拉加载的文字
// ref="名称" 可通过 _this.$refs.名称.方法名 调用组件内部的方法
- 表单
<template>
<form @submit="formSubmit" @reset="formReset">
// ... 表单元素
<view class="section btn-wrap">
<button type="button" class="login-btn yh-btn-big" form-type="submit">登录</button> // ... 提交按钮
</view>
</form>
</template>
methods: {
formSubmit(e) {
console.log('form发生了submit事件,携带数据为:', e.mp.detail.value)
},
formReset() {
console.log('form发生了reset事件')
}
}
- modal弹层组件
xxxModal.vue 弹层组件结构
// 弹层结构
<template> // v-if="变量" 控制弹层显示隐藏
<view class="modal-wrap" v-if="showModal" @touchmove.stop="preventTouchMove">
<!-- ① 遮罩层 -->
<view class="modal-mask"></view>
<!-- ② 弹出层 -->
<view class="modal-dialog message-modal-wrap">
<view class="modal-title">{{title}}</view>
<view class="modal-content">
<!-- ③ 内容 -->
</view>
<!-- ④ 底部放关闭图标 (也可以放按钮) -->
<view class="modal-footer" @click="onCancel">
<img src="/static/images/modal_icon_close@2x.png" data-status="cancel" class="icon-close">
</view>
</view>
</view>
</template>
// props 接收父组件传递值: showModal控制显示隐藏 title弹层标题
props: ['showModal','title'],
// 关闭弹层事件
methods: {
preventTouchMove(){}, // 禁止屏幕滚动 只需要一个空的函数
onCancel() {
this.$emit("hideModalFn") // 触发父组件关闭方法(注意没有传递值)
},
}
父组件.vue
// ① 导入弹层组件
import xxxModal from "@/components/xxxModal";
// ② 声明组件
components: { xxxModal },
// ③ 使用组件 使用:showModal :title传递值给弹层组件 @hideModal接收子组件发射的事件
<xxx-modal :showModal="showModal" :title="title" @hideModalFn="hideModalFn"></xxx-modal>
// ④ data定义要传递的值
data () {
return {
showModal: false,
title: '提示'
}
}
// ⑤ methods里定义子组件触发的父组件方法
methods: {
hideModalFn(){
this.$set(this.$data,'showModal',false); // 关闭弹层
}
}
// ⑥ 显示弹层的方法
<button @click="showModalFn"></button> // 某个元素绑定showModalFn点击事件
// methods里定义showModalFn方法
methods: {
showModalFn(){
this.$set(this.$data,'showModal',true); // 显示弹层
}
}
- 滑动删除demo
// demo结构
<ul>
<li v-for="(item,index) in List" :key="index" @touchstart="touchStart($event)" @touchend="touchEnd($event,index)" :data-type="item.type">
<view class="content">
// ... 展示出来的demo内容
</view>
<div class="delect" @click="delete(index,item.id)">
删除
</div> // 删除按钮,滑动前隐藏,左滑后展示
</li>
</ul>
// 函数
methods: {
// ① 在加载列表数据时初始化滑动属性type
queryList(){
// 添加滑动参数
this.List.forEach(function (item) {
this.$set(item,'type',0); // type 0 默认没有左滑
})
},
// ② 滑动开始获取startX
touchStart(e){
// 获取移动距离,可以通过打印出e,然后分析e的值得出
this.startX = e.mp.changedTouches[0].clientX;
},
// ③ 滑动结束获取endX
touchEnd(e,index){
// 获取移动距离
this.endX = e.mp.changedTouches[0].clientX;
// 移动距离大于60,滑动元素的type设为1,其它为零
if(this.startX-this.endX > 60){
for(let i=0;i<this.List.length;i++){
this.List[i].type = 0
}
this.List[index].type = 1
}
// 反向滑动(向右)则恢复原状
else if(this.startX-this.endX < -60){
for(let i=0;i<this.List.length;i++){
this.List[i].type = 0
}
}
},
// ④ 点击回复原状的函数(可选)
recover(index){
this.List[index].type = 0
},
// ⑤ 删除按钮的操作
delete(index,Id){
let _this = this;
wx.showModal({
title: '提示',
content: '确定删除吗?',
success(res) {
if (res.confirm) {
console.log('用户点击确定')
// 在这里发起删除请求
_this.List.splice(index,1);
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
},
}
// 主要样式
<style lang="less">
ul {
width: 100%;
li {
-webkit-transition: all 0.2s; // 动画过渡
transition: all 0.2s;
width: calc(~'100% + 90px'); // 这里的90px是删除按钮和左右间距的宽度
height: 74px;
line-height: 74px;
align-items:center;
display:flex;
.content {
width: calc(~'100% - 90px'); // 内容区减去这个宽度
}
.delect{
width: 40px;
height: 40px;
line-height:40px;
}
&[data-type="0"]{
transform: translate3d(0,0,0); // 没有滑动【重要】
}
&[data-type="1"]{
transform: translate3d(-40px,0,0); // 滑动后向左移动40px【重要】
}
}
}
</style>
五、样式类
公共样式放在App.vue的
<style></style>
标签内模块私有样式放在各模块的
<style></style>
标签内less常用语法
① 嵌套
<div class="parent">
<div class="child-one"></div>
<div class="child-two"></div>
</div>
// css写法
.parent {
background: #f8f8f8;
margin: 0 auto;
}
.parent .child-one {
color: red;
font-size: 14px;
}
.parent .child-two {
color: blue;
font-size: 16px;
}
// less写法
.parent {
background: #f8f8f8;
margin: 0 auto;
.child-one {
color: red;
font-size: 14px;
}
.child-two {
color: blue;
font-size: 16px;
}
}
② &的使用
<ul>
<li class="active"></li>
<li></li>
</ul>
// css 写法
ul li {
color: #333;
}
ul li.active {
color: blue;
}
// less 写法
ul {
li {
color: #333;
&.active { // 这里的 &.active == li.active
color: blue;
}
}
}
// 例如
li:after {
}
也可以写成
li {
&:after {
}
}
& 向上寻找
③ calc()
// css 写法
div {
calc(100% - 60px);
}
// less 写法
div {
calc(~'100% - 60px');
}
④ 注释
// less
div {
width: 100%;
height: 100%;
// color: #333;
// background: #f8f8f8; // 这两行就被注释掉了,不会被编译在样式里
margin: 0 auto;
}