(原) uni-app 学习 -- vue3

原创文章,请后转载,并注明出处。

uni-app一套代码多个平台运行,算是懒人和小团队的福音。

官网:https://uniapp.dcloud.io

vue是它的主要语言,之前对vue了解不多。既然新的开始,就从新版3开始学习。

vue官方文档等待以后再看,直接看uni的。

不同于现在html结构,它的结构变成这样(vue单文件组件规范)

    <template>  
        <view>  
        注意必须有一个view,且只能有一个根view。所有内容写在这个view下面。  
        </view>  
    </template>  
    <script>  
        export default {  
        }  
    </script>  
    <style>  
    </style>

template是网页部份; script是脚本部份; style是样式部份。好处是减少了文件管理的复杂,对于洁癖的我比较有好感。

外部文件引用

<script>
    var util = require('../util.js');   // 引用文件
    var formatedTime = util.formatTime(play); // 引用文件中的方法
</script>

在util.js中

    function formatTime(time) {  
        return time;//这里没写逻辑  
    }  
    module.exports = {  
        formatTime: formatTime  
    }

这与微信小程序差不多。

css外部引用也有变化

    <style>  
        @import "./common/uni.css";  
        .uni-hello-text{  
            color:#7A7E83;  
        }  
    </style>

js有所变化,已经有点象前后端的感觉了,即前端使用变量,后端来控制变量。

    <template>  
        <view>  
            <text>{{textvalue}}</text><!-- 这里演示了组件值的绑定 -->  
            <button :type="buttontype" @click="changetextvalue()">修改为789</button><!-- 这里演示了属性和事件的绑定 -->  
        </view>  
    </template>  
    <script>  
        export default {  
            data() {  
                return {  
                    textvalue:"123",  
                    buttontype:"primary"  
                };  
            },  
            onLoad() {  
                this.textvalue="456"//这里修改textvalue的值,其实123都来不及显示就变成了456  
            },  
            methods: {  
                changetextvalue() {  
                    this.textvalue="789"//这里修改textvalue的值,页面自动刷新为789  
                }  
            }  
        }  
    </script>

插值

最常见的文本插值

    <template>
        <view>
            <view>Message: {{ msg }}</view>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    msg: 'Hello Vue!'
                }
            }
        }
    </script>

JavaScript表达式

    <template>
         <view>
            <view>{{ number + 1 }}</view>
            <view>{{ ok ? 'YES' : 'NO' }}</view>
            <!-- 把一个字符串分割成字符串数组,颠倒其元素的顺序,把数组中的所有元素放入一个字符串 -->
            <view>{{ message.split('').reverse().join('') }}</view>
         </view>
    </template>
    <script>
      export default {
         data() {
            return {
              number:1,
              ok:true,
              message: 'Hello Vue!'
            }
         }
      }
    </script>

直接在{{}}中进行计算和函数运行

    <template>
      <view>
            <view v-for="(item,index) in 10">
            <!-- 通过%运算符求余数,实现隔行换色的效果 -->
            <view :class="'list-' + index%2">{{index%2}}</view>
         </view>
      </view>
    </template>
    <script>
      export default {
         data() {
            return { }
         }
      }
    </script>
    <style>
      .list-0{
         background-color: #aaaaff;
      }
      .list-1{
         background-color: #ffaa7f;
      }
    </style>

在双引号中也能进行运算?

指令

v-bind 动态绑定一个或多个属性,缩写为:

    <!-- 完整语法 -->
    <image v-bind:src="imgUrl"></image>
    <!-- 缩写 -->
    <image :src="imgUrl"></image>

    <button v-bind:disabled="isButtonDisabled">Button</button>

v-on 用于监听事件,缩写为@

    <!-- 完整语法 -->
    <view v-on:click="doSomething">点击</view>    
    <!-- 缩写 -->
    <view @click="doSomething">点击</view>

v-once 只渲染一次

    <!-- 单个元素 -->
    <view v-once>This will never change: {{msg}}</view>
    <!-- 有子元素 -->
    <view v-once>
        <text>comment</text>
        <text>{{msg}}</text>
    </view>

但看说明不支持h5和微信小程序

v-html 内容按html来支持

    <template>
        <view>
            <view v-html="rawHtml"></view>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    rawHtml: '<div style="text-align:center;background-color: #007AFF;"><div >我是内容</div><img src="https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/d8590190-4f28-11eb-b680-7980c8a877b8.png"/></div>'
                }
            }
        }
    </script>

data

    //正确用法,使用函数返回对象
    data() {
        return {
            title: 'Hello'
        }
    }

    //错误写法,会导致再次打开页面时,显示上次数据
    data: {
        title: 'Hello'
    }

    //错误写法,同样会导致多个组件实例对象数据相互影响
    const obj = {
        title: 'Hello'
    }
    data() {
        return {
            obj
        }
    }

Class 与 Style 绑定

:class 是 v-bind:class 的简写。可以与普通的 class 共存。

            <view class="static" :class="{ active: isActive}">hello uni-app</view>
            <view class="static" :class="{ active: isActive, 'text-danger': hasError }">hello uni-app</view>

这里通过判断isActive和hasError是否为真,添加class。

数组语法,也就是同时使用多个变量所对应的样式

    <template>
         <view>
            <view :class="[activeClass,errorClass]">hello uni-app</view>
         </view>
    </template>
    <script>
         export default {
              data() {
                    return {
                         activeClass: 'active',
                         errorClass: 'text-danger'
                    }
              }
         }
    </script>
    <style>
        .active{
            background-color: #007AFF;
        }
        .text-danger{
            font-size:60rpx;
            color:#DD524D;
        }
    </style>

渲染的结果为:

以下class通过computed中的函数计算返回,这样就更强大了,还避免前端复杂性。

    <template>
        <view>
            <view class="container" :class="computedClassStr">hello uni-app</view>
            <view class="container" :class="{active: isActive}">hello uni-app</view>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    isActive: true
                }
            },
            computed: {
                computedClassStr() {
                    return this.isActive ? 'active' : ''
                }
            }
        }
    </script>
    <style>
        .active {
            background-color: #007AFF;
            font-size:30px;
        }
    </style>

绑定内联样式

    <template>
        <view :style="{ color: activeColor, fontSize: fontSize + 'px' }">hello uni-app</view>
    </template>
    <script>
        export default {
            data() {
                return {
                    activeColor: 'red',
                    fontSize: 30
                }
            }
        }
    </script>

上面这个示例将变量引入了style,但很不直观。

    <template>
        <view :style="styleObject">hello uni-app</view>
    </template>
    <script>
        export default {
            data() {
                return {
                    styleObject: {
                      color: 'red',
                      fontSize: '13px'
                    }
                }
            }
        }
    </script>

这个示例就直接将脚本中变量包含的样式给了style。

同样,也可以用数组将多个样式应用到同一个元素

<view :style="[baseStyles, overridingStyles]">hello uni-app</view>

    <script>
        export default {
            data() {
                return {
                    baseStyles: {
                        color: 'green',
                        fontSize: '30px'
                    },
                    overridingStyles: {
                        'font-weight': 'bold'
                    }
                }
            }
        }
    </script>

多重值,用于不同浏览器环境下,匹配可以支持的值

 <view :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></view>

条件渲染

v-if v-else v-else-if

    <template>
        <view>
            <view v-if="seen">现在你看到我了</view>
            <view v-else>你看不到我了</view>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    seen: true
                }
            }
        }
    </script>

v-show 只是简单的显示与不显示,但都会渲染。即只是display属性的控制。

列表渲染

v-for

    <template>
        <view>
            <view v-for="(item, index) in items">
                 {{ parentMessage }} - {{ index }} - {{ item.message }}
            </view>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    parentMessage: 'Parent',
                    items: [
                        { message: 'Foo' },
                        { message: 'Bar' }
                    ]
                }
            }
        }
    </script>

它也可以用来遍历json对象

    <template>
        <view>
            <view v-for="(value, name, index) in object">
                 {{ index }}. {{ name }}: {{ value }}
            </view>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    object: {
                        title: 'How to do lists in Vue',
                        author: 'Jane Doe',
                        publishedAt: '2021-05-10'
                    }
                }
            }
        }
    </script>

结果为

    0.title: How to do lists in Vue,
    1.author: Jane Doe,
    2.publishedAt: 2021-05-10

事件处理

多事件处理

    <template>
        <view>
            <!-- 这两个 one() 和 two() 将执行按钮点击事件 -->
            <button @click="one($event), two($event)">
              Submit
            </button>
        </view>
    </template>
    <script>
        export default {
            methods: {
                one(event) {
                    // first handler logic...
                    console.log("event1: ",event);
                },
                two(event) {
                    // second handler logic...
                    console.log("event2: ",event);
                }
            }
        }
    </script>

事件修饰符

.stop 阻止冒泡
... 还有几个仅h5支持


<view @click.stop="doThis"></view>

事件映射表

左侧为 WEB 事件,右侧为 uni-app 对应事件

        click: 'tap',
        touchstart: 'touchstart',
        touchmove: 'touchmove',
        touchcancel: 'touchcancel',
        touchend: 'touchend',
        tap: 'tap',
        longtap: 'longtap', //推荐使用longpress代替
        input: 'input',
        change: 'change',
        submit: 'submit',
        blur: 'blur',
        focus: 'focus',
        reset: 'reset',
        confirm: 'confirm',
        columnchange: 'columnchange',
        linechange: 'linechange',
        error: 'error',
        scrolltoupper: 'scrolltoupper',
        scrolltolower: 'scrolltolower',
        scroll: 'scroll'

表单输入绑定

    <template>
        <view>
            <input v-model="message" placeholder="edit me">
            <text>Message is: {{ message }}</text>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    message:""
                }
            }
        }
    </script>

uni-app表单组件

H5 的 select 标签用 picker 组件进行代替

    <template>
        <view>
            <picker @change="bindPickerChange" :value="index" :range="array">
                <view class="picker">
                    当前选择:{{array[index]}}
                </view>
            </picker>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    index: 0,
                    array: ['A', 'B', 'C']
                }
            },
            methods: {
                bindPickerChange(e) {
                    console.log(e)
                    this.index = e.detail.value
                }
            }
        }
    </script>

表单元素 radio 用 radio-group 组件进行代替

    <template>
        <view>
            <radio-group class="radio-group" @change="radioChange">
                <label class="radio" v-for="(item, index) in items" :key="item.name">
                    <radio :value="item.name" :checked="item.checked" /> {{item.value}}
                </label>
            </radio-group>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    items: [{
                            name: 'USA',
                            value: '美国'
                        },
                        {
                            name: 'CHN',
                            value: '中国',
                            checked: 'true'
                        },
                        {
                            name: 'BRA',
                            value: '巴西'
                        },
                        {
                            name: 'JPN',
                            value: '日本'
                        },
                        {
                            name: 'ENG',
                            value: '英国'
                        },
                        {
                            name: 'TUR',
                            value: '法国'
                        }
                    ]
                }
            },
            methods: {
                radioChange(e) {
                    console.log('radio发生change事件,携带value值为:', e.target.value)
                }
            }
        }
    </script>

计算属性的 setter

    <template>
        <view>
            <view>{{ fullName }}</view>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    firstName: 'Foo',
                    lastName: 'Bar'
                }
            },
            computed: {
                fullName: {
                    // getter
                    get(){
                        return this.firstName + ' ' + this.lastName
                    },
                    // setter
                    set(newValue){
                        var names = newValue.split(' ')
                        this.firstName = names[0]
                        this.lastName = names[names.length - 1]
                    }
                }
            }
        }
    </script>

侦听器watch

当你有一些数据需要随着其它数据变动而变动时,就可以使用Watch来监听他们之间的变化。

    <template>
        <view>
            <input type="number" v-model="a" style="border: red solid 1px;" />
            <input type="number" v-model="b" style="border: red solid 1px;" />
            <view>总和:{{sum}}</view>
            <button type="default" @click="add">求和</button>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    a:1,
                    b:1,
                    sum: ""
                }
            },
            watch: {
                /* 使用watch来响应数据的变化,第一个参数为newVal新值,第二个参数oldVal为旧值*/
                a: function(newVal, oldVal) {
                    console.log("a--newVal: ", newVal, "a--oldVal: ",oldVal);
                },
                b: function(newVal, oldVal) {
                    console.log("b--newVal: ", newVal, "b--oldVal: ",oldVal);
                }
            },
            methods: {
                add() {
                    this.sum = parseInt(this.a) + parseInt(this.b)
                }
            }
        }
    </script>

在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调:

    <template>
        <view>
            <input type="number" v-model="a" style="border: red solid 1px;" />
            <input type="number" v-model="b" style="border: red solid 1px;" />
            <view>总和:{{sum}}</view>
            <button type="default" @click="add">求和</button>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    a:1,
                    b:1,
                    sum: ""
                }
            },
            watch: {
                a: {
                    handler(newVal, oldVal) {
                        console.log("a------: ", newVal, oldVal);
                    },
                    immediate: true//初始化绑定时就会执行handler方法
                },
                b: {
                    handler(newVal, oldVal) {
                        console.log("b------: ", newVal, oldVal);
                    },
                    immediate: true//初始化绑定时就会执行handler方法
                }
            },
            methods: {
                add() {
                    this.sum = parseInt(this.a) + parseInt(this.b)
                }
            }
        }
    </script>

为了发现对象内部值的变化,可以在选项参数中指定 deep: true 。深度监听一个对象整体的变化(即监听对象所有属性值的变化)

    <template>
        <view>
            <input type="number" v-model="obj.a" style="border: red solid 1px;" />
            <input type="number" v-model="obj.b" style="border: red solid 1px;" />
            <view>总和:{{sum}}</view>
            <button type="default" @click="add">求和</button>
        </view>
    </template>
    <script>
        export default {
            data() {
                return {
                    obj: {
                        a: 1,
                        b: 1,
                    },
                    sum:""
                }
            },
            watch: {
                obj: {
                    handler(newVal, oldVal) {
                        console.log('obj-newVal:' + JSON.stringify(newVal), 'obj-oldVal:' + JSON.stringify(oldVal), );
                    },
                    deep: true//对象中任一属性值发生变化,都会触发handler方法
                }
            },
            methods: {
                add() {
                    this.sum = parseInt(this.obj.a) + parseInt(this.obj.b)
                }
            }
        }
    </script>

如果不想监听 obj 中其他值,只想监听 obj.a 的值的变化,可以写成字符串形式监听。

    export default {
        data() {
            return {
                obj: {
                    a: 1,
                    b: 1,
                }
            }
        },
        watch: {
            "obj.a": {//监听obj对象中的单个属性值的变化
                handler(newVal, oldVal) {
                    console.log('obj-newVal:' + newVal, 'obj-oldVal:' + oldVal);
                }
            }
        }
    }

组件

相关文章