uniapp前端开发基础知识 | 青训营笔记
这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天
虽然我是后端基础班的同学,但是我还是学习了一部分前端的知识,希望能够将抖音项目的前后端完整地设计出来。
开发工具
HBuilder-X
uni-app程序开发
这是一个测试项目,仅仅用于学习vue和uniapp开发的基础知识
前置知识学习
- 前端三件套
- Vue框架
- 一门后端语言(这里采用node.js进行,后期会重构成golang语言)
前端知识学习
生命周期
- 应用生命周期
- 应用生命周期:可以通过App.vue当中的某些函数进行监视
- 通过下面的函数可以做到对应用进行一定的监听,例如其中的函数onLaunch是程序开始运行,onHide是后台运行,onShow是正在运行(前台),onLoad是页面正在加载
- 应用生命周期:可以通过App.vue当中的某些函数进行监视
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
- 页面生命周期
- 通过我们对某一个页面监听的时候,页面第一次打开的时候会调用onLoad,如果切换到其他页面会调用onHide,隐藏之后打开只会调用onShow,而不会调用onLoad
在uni-app当中使用vue
创建变量
对于下面一个模板,我们需要创建一个变量,那么就在data当中写入,然后可以利用{{}}来书写模板语法,这里类似于python-flask当中的jinja2语法,利用双大括号来进行
<template>
<view>
{{test}}
</view>
</template>
<script>
export default {
// 这里用于存放变量,然后在上面使用模板语法
data() {
return {
test:'hello world'
}
},
onLoad() {
console.log("Loading")
},
onShow(){
console.log("Show")
},
onHide(){
console.log("Hide")
},
methods: {
}
}
</script>
<style>
</style>
同时比较优秀的一点是,如果我们修改data,页面也会重新渲染,也就是同步的发生了修改
下面还有一种做法,可以利用指令"v-text"进行绑定
<template>
<view v-text="test" class="content">
</view>
</template>
利用上面的指令就也可以让我们其中填入text变量的值
同样的我们也可以使用v-html="xxxx"的样子,这个与v-text的不同在于,v-html会进行html解析和渲染,而利用v-text仅仅会将我们填入的数据当作字符串来展现
这里需要注意的是v-text的使用等效于{{}}的模板语法
样式绑定
*一般方式
- 我们可以利用简单的css选择器,选择在html当中的标签,利用class和id等,然后在页面当中的style当中编写
- 对于一些全局的样式,我们可以在App.vue当中进行编写
当然上面的方式都是利用原本三件套的编写方式
*利用vue的方式
- 我们可以先创建一个变量在data里面,然后利用 v-bind:style = "style" 就可以进行操作了
<template>
<view v-text="test" class="content" v-bind:style="style">
</view>
</template>
<script>
export default {
// 这里用于存放变量,然后在上面使用模板语法
data() {
return {
test:'hello world',
style:'font-size:30px; color:red;'
}
},
onLoad() {
console.log("Loading")
},
onShow(){
console.log("Show")
},
onHide(){
console.log("Hide")
},
methods: {
}
}
</script>
<style>
</style>
利用上面的方式就可以进行绑定
当然也有简略的语法,类似于下面的
<template>
<view :class="test" v-bind:style="style">
hello world
</view>
</template>
<script>
export default {
// 这里用于存放变量,然后在上面使用模板语法
data() {
return {
test:'text',
style:'font-size:30px; color:red;'
}
},
onLoad() {
console.log("Loading")
},
onShow(){
console.log("Show")
},
onHide(){
console.log("Hide")
},
methods: {
}
}
</script>
<style>
</style>
直接:就可以进行变量的绑定了,同时是动态变化的,如果变量发生改变,会重新发生渲染,这样我们就可以实现一个动态的效果
事件绑定
练习:点击hello world的时候,让我们的字体发生颜色的改变 下面的函数利用v-on:click绑定了函数click,这样我们点击的时候就会调用click函数,然后实现颜色的切换
<template>
<!-- 我们这里绑定了click事件,我们应该在methods当中定义这个函数 -->
<view :class="test" v-bind:style="style" v-on:click="click">
hello world
</view>
</template>
<script>
export default {
// 这里用于存放变量,然后在上面使用模板语法
data() {
return {
test:'text',
style:'font-size:30px; color:red;'
}
},
onLoad() {
console.log("Loading")
},
onShow(){
console.log("Show")
},
onHide(){
console.log("Hide")
},
methods: {
click:function(){
this.style="font-size:30px; color:black;"
}
}
}
</script>
<style>
</style>
当我们点击的时候就可以很好的完成这样的效果,我们的v-on:click可以简写成为@click就完成了
条件渲染
练习:利用按钮,让我们显示的文本隐藏,再次点击让文本重新显示
下面的代码利用了v-if进行了条件渲染,当v-if当中绑定的表达式为true的时候,那就会显示,否则就不会显示,这样我们点击的时候就可以完成我们可以利用多种方式实现click的逻辑,例如使用if判断,使用三目运算符,都可以简单的进行。
<template>
<view>
<!-- 当v-if当中的值为true的时候,下面的文本会显示,否则不会显示 那么这样我们可以绑定一个变量,然后通过button来改变这个变量-->
<view :class="test" v-bind:style="style" v-if="show">
hello world
</view>
<button @click="click">
按钮
</button>
</view>
</template>
<script>
import { vShow } from "vue"
export default {
// 这里用于存放变量,然后在上面使用模板语法
data() {
return {
test:'text',
style:'font-size:30px; color:red;',
show:true
}
},
onLoad() {
console.log("Loading")
},
onShow(){
console.log("Show")
},
onHide(){
console.log("Hide")
},
methods: {
click:function(){
this.show = !this.show
},
}
}
</script>
<style>
</style>
这里有另外一个元素是v-show,两者的区别在于v-show并不会删除原本的元素,而使用v-if会删除原本的元素,再点击的时候会重新渲染。
看下面的代码
<view :class="test" v-bind:style="style" v-if="show">
hello world
</view>
<view v-else>good bye world</view>
这里有一个新的标签是v-else,这里实现了两者的渲染,v-if必须是和其相邻的标签
列表渲染
练习:当我们需要使用大量相同的标签的时候,例如我们打印10个hello world
代码都相同,如果我们重复写的话,就会有很多的冗余,所以我们可以使用v-for列表渲染
<template>
<view class="content">
<view class="" v-for="item in list">
hello world
{{item}}
</view>
</view>
</template>
<script>
export default {
data() {
return {
list:[1,2,3,4,5,6,7,8,9,10]
}
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
这样的话我们就可以完成了
当然也可以看下面一段代码
<template>
<view class="content">
<view class="" v-for="(item, index) in list" :key="index">
hello world
{{item}} ----- {{index}}
</view>
</view>
</template>
<script>
export default {
data() {
return {
list:[1,2,3,4,5,6,7,8,9,10]
}
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
v-model的使用
题目:我们需要读取input当中的文本,并存储为一个变量
我们通过v-model实现了双向绑定
看下面的代码实现:
<template>
<view class="content">
<!-- 我们可以将其中的内容存储到一个变量当中 -->
<input type="text" value="" v-model="text"/>
<button type="primary" @click="click">按钮</button>
</view>
</template>
<script>
export default {
data() {
return {
text : ''
}
},
onLoad() {
},
methods: {
click(){
console.log(this.text)
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
也就是我们修改text的时候,里面的内容会发生改变,如果改变input当中的内容,text的变量值也会发生改变
这样我们在这里可以实现一个更加复杂的逻辑,我们每次点击提交,让上面input的内容加入到下面,同时清空input里面的内容
<template>
<view class="content">
<!-- 我们可以将其中的内容存储到一个变量当中 -->
<input type="text" value="" v-model="text"/>
<button type="primary" @click="click">按钮</button>
<view>
<view class="" v-for="item in list">
{{item}}
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
text : '',
list : ["hello", "world"]
}
},
onLoad() {
},
methods: {
click(){
this.list.push(this.text)
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
上面的实现利用了以下的思路:
- 利用v-model和变量的双向绑定特征,当点击的时候,将文本加入列表当中
- 利用了@click绑定函数
- 利用了v-for的方式
- 利用vue和变量的响应能力,当vue变量发生改变的时候,与其绑定的标签也会发生重新渲染
vue实例的生命周期
参考资料
相关概念
- 钩子:钩子函数 其实钩子就类似于这种回调函数的形式,通过通知的方式告知,某个动作要执行了
- 挂载:参考上面的资料
vue的整体流程
我们可以看到官方提供了很多的钩子函数,这样我们可以在这些时候进行一些操作
<template>
<view class="content">
<button type="primary" @click="click">改变</button>
<view class="">
{{text}}
</view>
</view>
</template>
<script>
export default {
data() {
return {
text:'hello'
}
},
onLoad() {
},
methods: {
click(){
this.text = "你好"
}
},
beforeCreate(){
// 在创建之前是没有data里面的数据的,所以打印出来的是undefined
console.log(this.text)
},
created(){
console.log(this.text)
},
beforeMount() {
console.log(1)
},
// mounted 挂载其实就是页面渲染到应该有的位置
mounted() {
console.log(2)
},
beforeUpdate() {
// 在更新的时候进行
console.log("beforeUpdate")
},
updated(){
console.log("Updated")
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
上面是我们使用一些钩子函数的实例以及注释,这样我们就可以使用一些操作
计算属性、方法和监听
计算属性
- 当我们修改计算属性当中使用的变量的时候,会重新调用计算属性然后重新渲染页面
- 当我们修改与计算属性(函数)无关的变量的时候,则不会重新调用计算属性
<template>
<view class="">
{{fullText}}
<button type="primary" @click="click">按钮</button>
</view>
</template>
<script>
export default {
data() {
return {
firstTest:'hello',
lastText:'world'
}
},
onLoad() {
},
methods: {
click(){
this.firstTest = 'tt'
}
},
computed:{
fullText(){
console.log("计算属性")
// 当我们修改属性之后,再次调用这个属性,但是如果我们修改和当前计算属性不相关的变量的时候
// 则不会重复调用
return this.firstTest + " " + this.lastText
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
但是如果我们使用一个普通的函数(在methods当中定义)的函数呢?
方法
- 使用方法由于其无论改变哪个变量(有关和无关)都会重新调用,这样会降低性能
- 调用方法需要加()
<template>
<view class="">
{{fullText()}}
<button type="primary" @click="click">按钮</button>
</view>
</template>
<script>
export default {
data() {
return {
firstTest:'hello',
lastText:'world'
}
},
onLoad() {
},
methods: {
click(){
this.firstTest = 'tt'
},
fullText(){
console.log("方法")
return this.firstTest+ " " + this.lastText
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
监听
- 监听是对某一变量的监听,其名称等于需要被监听的变量的名称
- 当变量发生改变的时候会调用监听,然后重新进行渲染
代码如下:
<template>
<view class="">
{{fullText}}
<button type="primary" @click="click">按钮</button>
</view>
</template>
<script>
export default {
data() {
return {
firstText:'hello',
lastText:'world',
fullText: "hello world"
}
},
onLoad() {
},
methods: {
click(){
this.firstText = 'tt'
}
},
watch:{
firstText(){
console.log("first")
this.fullText = this.firstText + " " + this.lastText
},
lastText(){
console.log("last")
this.fullText = this.firstText + " " + this.lastText
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
对于上面的代码我们就监听了两个变量,当firstText发生改变的时候会调用firstText的监听函数
父子组件传值
- 创建组件在components里面,这里起名为child,然后引用,在页面的script里面使用import和components指令,得到结果
<template>
<view class="">
<child></child>
</view>
</template>
<script>
import child from '../../components/child.vue'
export default {
components:{
child
},
data() {
return {};
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
关于命名的问题
如果我们命名一个组件的名称是chiLd,那么我们在调用组件的时候就需要使用chi-ld,代码如下:
<template>
<view class="">
<chi-ld></chi-ld>
</view>
</template>
<script>
import chiLd from '../../components/child.vue'
export default {
components:{
chiLd
},
data() {
return {};
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
此时我们就可以实现这些操作
父子组件传值
这里直接用两段代码来直接说明
父组件
<template>
<view class="">
<!-- 这里也是监听到我们emit过来的change事件,此时会向test函数当中传入一个变量,就是我们emit过来的那个变量title,作为形参res -->
<child @change="changeFather" :text="text" :hello="test"></child>
{{title}}
</view>
</template>
<script>
import child from '../../components/child.vue'
export default {
components:{
child
},
data() {
return {
test:"我是hello",
text:'我是父组件',
title:"我是父组件"
};
},
onLoad() {
},
methods: {
changeFather(res){
console.log(res)
this.title = res
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
子组件
<template>
<view>
{{text}}
{{hello}}
<button type="primary" @click="click">传值</button>
</view>
</template>
<script>
export default {
name:"child",
props:['text','hello'], // 用来接收父组件传给子组件的数据
data() {
return {
title:"我是子组件"
};
},
methods:{
click(){
// click触发一个事件,然后传递值到父组件当中
this.$emit('change', this.title)
}
}
}
</script>
<style>
</style>
从上面的代码看出两种的基本步骤:
利用父组件传递给子组件:
- 在父组件当中定义变量(假设为text)
- 然后我们在调用的child标签当中加入一个属性 ':子组件当中接收的变量名 : "text"'
- 然后我们在子组件当中声明一个props数组,然后存储形式为 props : ['子组件当中接收的变量名1','子组件当中接收的变量名2',....]
- 此时就可以在组件当中将这些变量名当作一般的变量使用,利用模板语法等就可以进行操作
利用子组件传递给父组件:
- 在子组件当中定义变量(假设为title)
- 定义一个方法,然后让方法绑定某个事件名称,上面的测试样例当中使用的是change,绑定使用的是click函数,利用$emit("change",this.title)传入
- 事件的名称就是change了,然后我们需要在父组件当中定义child的地方来进行,将change作为一个属性 $change: "click",这样的话,我们利用上面emit传入的参数this.title就可以作为参数传入click函数。
- 按照上面的方法就可以实现传值
组件参数校验
在子组件对父组件当中的变量进行约束,限制变量类型等
<template>
<view>
{{text}}
{{hello}}
<button type="primary" @click="click">传值</button>
</view>
</template>
<script>
export default {
name:"child",
// 用来接收父组件传给子组件的数据
// 进行约束
props:{
// 可以有多种形式进行约束
'text' : [String, Number],
'hello': {
type:String
default:3 // 这里可以设置为一个默认值
}
},
data() {
return {
title:"我是子组件"
};
},
methods:{
click(){
// click触发一个事件,然后传递值到父组件当中
this.$emit('change', this.title)
}
}
}
</script>
<style>
</style>
按照上面的多种形式都可以进行约束,当然也可以就一个值,也是可以的。