【Kotlin-JetPack】融合组件(登录注册,bottombar)

2023-11-10 21:10

本文主要是介绍【Kotlin-JetPack】融合组件(登录注册,bottombar),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1. APP下载地址: https://wws.lanzous.com/iAKuok3dvah密码:e306
  2. Github: https://github.com/kirikaTowa/TBzcibDZY

全体包

 implementation 'io.supercharge:shimmerlayout:2.1.0'implementation 'androidx.navigation:navigation-fragment-ktx:2.1.0'implementation 'androidx.navigation:navigation-ui-ktx:2.1.0'//添加anko库implementation 'org.jetbrains.anko:anko:0.10.8'//添加ButtonBar组件implementation 'com.roughike:bottom-bar:2.3.1'implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-beta01'def room_version = "2.2.5"implementation "androidx.room:room-runtime:$room_version"kapt "androidx.room:room-compiler:$room_version"// optional - Kotlin Extensions and Coroutines support for Roomimplementation "androidx.room:room-ktx:$room_version"// optional - Test helperstestImplementation "androidx.room:room-testing:$room_version"implementation 'com.roughike:bottom-bar:2.3.1'implementation 'androidx.fragment:fragment-ktx:1.2.2'implementation 'com.github.bumptech.glide:glide:4.10.0'

1. 登录模块

1.界面绘制,圆角和方块弧通过drawable控制shape绘制,背景图来自Iphone壁纸

  1. 假定默认登录注册密码为root 12345
    在这里插入图片描述

2. Room初始三件套(实体类,Dao层,DataBase库)

  1. 实体类(只有主键可设定自增,一般登录注册是从网上接口拿数据的)
@Entity//Room表示创建实体类
class User(account: Long, psd: String) {@PrimaryKeyvar account: Long = account@ColumnInfo(name = "password")var psd: String = psd}
  1. Dao层
@Dao //Database access object
interface UserDao {@Insertfun insertUsers(vararg users: User?)@Update//返回修改的记录条数fun updateUsers(vararg users: User?) //通过id进行替换内容@Deletefun deleteUsers(vararg users: User?)@Query("DELETE FROM User")//删除所有内容fun deleteAllUsers();@Query("SELECT * FROM User ")//降序查询fun getAllUsers():List<User>@Query("SELECT * FROM User WHERE account In(:account)")//查询账号是否存在fun getUser(account:Long):LiveData<User>@Query("SELECT * FROM User ")fun getAllWordsLive():LiveData<List<User>>
}
  1. Database控制
@Database(entities = [User::class],version = 2,exportSchema = false)abstract class UserDatabase: RoomDatabase() {//若有多个entities则返回多个Daocompanion object {var INSTANCE: UserDatabase? = null@Synchronized//如果有多个客户端  且同时instance时保证不会有碰撞 只有一个instance生成open fun getDatabase(context: Context): UserDatabase? {//静态类的静态方法写openif (INSTANCE == null) {INSTANCE = Room.databaseBuilder(context.applicationContext, UserDatabase::class.java, "user_database").fallbackToDestructiveMigration()//.allowMainThreadQueries()//先允许主线程运行//.addMigrations(MIGRATION_6_7).build()}return INSTANCE}}abstract fun getUserDao(): UserDao
}
  1. 导入自己喜欢的BaseActivity包,目前userdatabase对象和userdao只是为了登录注册服务的,以后可以尝试一下范型。并且单是抽取积累的话登录注册基类+封装也挺好的看个人需求。

//所有Activity基类
abstract class BaseActivity: AppCompatActivity(), AnkoLogger {private var userdatabase: UserDatabase?=nulllateinit var userdao: UserDaooverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(getLayoutid())//基类抽取界面组initListener()//子类中并非一定要实现,创建一个function即可initDate()//数据支持}//    初始化数据,非私有加入open关键字才能复写open protected fun initDate() {userdatabase=UserDatabase.getDatabase(applicationContext)!!userdao=userdatabase?.getUserDao()!!}//    adapter listeneropen protected fun initListener(){}//创建抽象类以供获取Layout,abstract不用加abstract fun getLayoutid():Int//在基类线中弹toast解决线的问题   1?protected fun myToast(msg:String){runOnUiThread{toast(msg)}}//开启activity并且finish当前界面,添加内联支持inline 与reified//进入看发现限制是Activity或Activity子类  reified用于找到传入泛型具体的类 下面内部就可以获取Tclass名(所以直接传泛型无法获取名称)inline  fun <reified T:BaseActivity>startActivityAndFinish(){startActivity<T>()finish()}
}
  1. 具体登录代码,用onclick绑定界面,写监听怪麻烦的,以后用databind时改也方便。

class LoginActivity : BaseActivity() {lateinit var  userviewModel:FindUserModelvar loginFlag:Boolean=falseoverride fun getLayoutid(): Int {return R.layout.activity_login}override fun initDate() {super.initDate()userviewModel = ViewModelProvider(this).get(FindUserModel::class.java)}fun LoginUser(v:View) {loginFlag=truevar textcount = Account_text.text.toString()var textpws = Password_text.text.toString()if (textcount.isEmpty()) {myToast("请输入用户名")}if (textpws.isEmpty()) {myToast("请输入密码")}if (!textcount.isEmpty() && !textpws.isEmpty()) {userviewModel.findUser = userdao.getUser(textcount.toLong())userviewModel.findUser?.let {userviewModel.findUser!!.observe(this, Observer {if (loginFlag==true){if ((it!=null)){if (  it.psd.equals(textpws)) {myToast("登录成功")startActivityAndFinish<MainActivity>()} else {myToast("账号或密码错误")}}else{myToast("用户不存在")}}})}}}fun IntoRegist(v:View){startActivity<RegistActivity>()}}

2. 注册模块

1.界面绘制,圆角和方块弧通过drawable控制shape绘制

在这里插入图片描述

  1. 代码

class RegistActivity : BaseActivity() {lateinit var  userviewModel:FindUserModelvar registFlag:Boolean=falseoverride fun getLayoutid(): Int {return R.layout.activity_regist}override fun initDate() {super.initDate()userviewModel = ViewModelProvider(this).get(FindUserModel::class.java)}fun RegistUser(v: View) {//会自动绑定get方法 插入成功后会自动get 设置个变量registFlag=truevar textcount = Input_account.text.toString()var textpws = Input_password.text.toString()var textpwsre = Input_passwordreput.text.toString()if (textcount.isEmpty()){ myToast("请输入用户名") }if (textpws.isEmpty()){ myToast("请输入密码") }if (textpwsre.isEmpty()){ myToast("请确认密码") }if (!textpwsre.equals(textpws)){ myToast("两次密码输入不一致") }if (!textcount.isEmpty() && !textpws.isEmpty() && !textpwsre.isEmpty() && textpwsre.equals(textpws)) {userviewModel.findUser = userdao.getUser(textcount.toLong())userviewModel.findUser?.let {userviewModel.findUser!!.observe(this, Observer {if (registFlag==true){if ((it!=null)){Input_account.text.clear()myToast("账户已存在")}else{registFlag=falsevar user = User(textcount.toLong(), textpws)InsertAsyncTask(userdao).execute(user)//增设查询该条记录myToast("插入成功")Handler().postDelayed(Runnable { startActivityAndFinish<LoginActivity>() }, 1000)}}})}}}internal class InsertAsyncTask(private val userdao: UserDao) : AsyncTask<User?, Unit, Unit>() {//在后台工作override fun doInBackground(vararg params: User?) {publishProgress()//该方法用于一段时间报告工作进度userdao.insertUsers(*params)}}
}

3.FragmentUtil控制首页与bottombar切换

1. 在fragment中获取AC和对应Context方式,

在这里插入图片描述

2. 建立App类,用于处理主线程回调,并且声明

  1. android:name ,它是用来app启动时来关联一个application的,默认关联的是android.app.Application,当app启动时,会默认创建一个application的实例 ,当在Activity中调用getApplication()方法时 ,就会返回这个实例,所以这个android:name 指定的类就有点似于全局变量的作用吧 , 用来存储数据供给整个 Activity 使用
class App: Application() {companion object{val handler= Handler()//主线程静态handler}override fun onCreate() {super.onCreate()}
}
  1. 样例
    在这里插入图片描述

4. 建立对应的货物三件套

1. 三件套

在这里插入图片描述

2.货物实体类

@Entity
class Goods(goodscode: Int, goodsname: String, goodssort: String, goodsprice: Int,goodspricecount: Float, goodssum: Int, goodsstate: Boolean, goodsimageuri: String?
)  {@PrimaryKey(autoGenerate = true)var id = 0@ColumnInfo(name = "goods_code")var goodscode: Int = goodscode@ColumnInfo(name = "goods_name")var goodsname: String = goodsname@ColumnInfo(name = "goods_sort")var goodssort: String = goodssort@ColumnInfo(name = "goods_price")var goodsprice: Int = goodsprice@ColumnInfo(name = "goods_count")var goodspricecount: Float = goodspricecount//折扣 0.23@ColumnInfo(name = "goods_sum")var goodssum: Int = goodssum//控制上架下架@ColumnInfo(name = "goods_state")var goodsstate: Boolean = goodsstate@ColumnInfo(name = "goods_imageuri")var goodsimageuri:String?=goodsimageuri
}

2.BaseFragment中初始化dao和database,来到主fragment,点击插入,搞定。


class HomeFragment: BaseFragment() {override fun initView(): View? {return View.inflate(context, R.layout.fragment_home, null)}override fun initData() {super.initData()Insert_button.setOnClickListener {var goods:Goods = Goods(1,"充电宝","10",100,1.0f,200,true,null)var  goods1:Goods = Goods(1,"充电宝","10",100,1.0f,200,true,null)goodsdao.insertGoods( goods, goods1)updateView();}/*       Delete_button.setOnClickListener {var word:Word = Word("Word","世界")word.setId(40)worddao.deleteWords(word)updateView()}*/Deleteall_button.setOnClickListener{goodsdao.deleteAllGoods()updateView()}
/*        Update_button.setOnClickListener {var word:Word = Word("Word","世界")word.setId(40)worddao.updateWords(word)updateView()}*/}fun updateView(){var list:List<Goods> =goodsdao.getAllGoods()var text=""for (i in (0 until list.size)){var goods:Goods =list.get(i)text+=""+goods.goodsname+goods.goodsprice;}Text_goodsname.text=text}}

在这里插入图片描述

3. 迁移,将商品上架放其他位置-第三个,然后首页展示,测试没问题

在这里插入图片描述


class InGoodsFragment: BaseFragment() {var goodsCode: Int?=nullvar goodsname: String?=nullvar goodssort: String?=nullvar goodsprice: Int?=nullvar goodspricecount: Float?=nullvar goodssum: Int?=nullvar goodsstate: Boolean=truevar goodsimageuristring: String?=nullvar goodsimageuri: Uri?=nullcompanion object {val TAKE_PHOTO = 1val CHOOSE_PHOTO = 2}override fun initView(): View? {return View.inflate(context, R.layout.fragment_ingoods, null)}override fun initListener() {Switch_state.setOnCheckedChangeListener { buttonView, isChecked ->goodsstate=isChecked}Button_inphoto.setOnClickListener {if (getActivity()?.applicationContext?.let { it1 -> ContextCompat.checkSelfPermission(it1, Manifest.permission.WRITE_EXTERNAL_STORAGE) } !== PackageManager.PERMISSION_GRANTED) {getActivity()?.let { it1 -> ActivityCompat.requestPermissions(it1, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1) }} else {openAlbum()}}Button_incamera.setOnClickListener {val simpleDateFormat = SimpleDateFormat("yyyy_MM_dd_HH_mm_ss") // HH:mm:ssval date = Date(System.currentTimeMillis())var changeCode=simpleDateFormat.format(date)changeCode=changeCode+".jpg"println("1111111111111${changeCode}")// 1. 创建File对象,用于存储拍照后的图片val outputImage = File(getActivity()?.externalCacheDir, changeCode)println("11111111111"+outputImage)try {if (outputImage.exists()) {outputImage.delete()}outputImage.createNewFile()} catch (e: IOException) {e.printStackTrace()}if (Build.VERSION.SDK_INT < 24) {goodsimageuri = Uri.fromFile(outputImage)} else {goodsimageuri = getActivity()?.applicationContext?.let { it1 ->FileProvider.getUriForFile(it1,"com.ywjh.cameraalbumtest.fileprovider",outputImage)}}// 启动相机程序val intent = Intent("android.media.action.IMAGE_CAPTURE")intent.putExtra(MediaStore.EXTRA_OUTPUT, goodsimageuri)startActivityForResult(intent, TAKE_PHOTO)}Button_submitgoods.setOnClickListener {if (In_code.text!=null &&  In_goodsname.text!=null && In_goodssort.text!=null && In_goodsprice!=null&& In_goodscount.text!=null && In_goodssum.text!=null && goodsimageuristring!=null){goodsCode=In_code.text.toString().toInt()goodsname=In_goodsname.text.toString()goodssort=In_goodssort.text.toString()goodsprice=In_goodsprice.text.toString().toInt()goodspricecount=In_goodssort.text.toString().toFloat()goodssum=In_goodssum?.text.toString().toInt()var goods: Goods = Goods(goodsCode!!,goodsname!!,goodssort!!,goodsprice!!, goodspricecount!!, goodssum!!, goodsstate,goodsimageuristring)goodsdao.insertGoods( goods)}else{/*             println("1111"+In_code.text!=null)println("1112"+ In_goodsname.text!=null)println("1113"+In_goodssort.text!=null)println("1114"+In_goodsprice==null)println("1115"+In_goodscount.text)println("1116"+In_goodssum.text)println("1117"+goodsimageuristring)*/myToast("请补全信息及上传图片")}}}override fun initData() {super.initData()}override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {when (requestCode) {TAKE_PHOTO -> if (resultCode == Activity.RESULT_OK) {try {goodsimageuristring=goodsimageuri.toString()// 将拍摄的照片显示出来val bitmap = BitmapFactory.decodeStream(goodsimageuristring?.let {getActivity()?.contentResolver?.openInputStream(it.toUri())})imageView.setImageBitmap(bitmap)} catch (e: Exception) {e.printStackTrace()}}CHOOSE_PHOTO -> if (resultCode == Activity.RESULT_OK) {// 判断手机系统版本号if (Build.VERSION.SDK_INT >= 19) {// 4.4及以上系统使用这个方法处理图片if (data != null) {handleImageOnKitKat(data)}} else {// 4.4以下系统使用这个方法处理图片if (data != null) {handleImageBeforeKitKat(data)}}}}}//4.4后 判断封装情况@TargetApi(19)private fun handleImageOnKitKat(data: Intent) {var imagePath: String? = nullval uri = data.dataLog.d("TAG", "handleImageOnKitKat: uri is $uri")if (DocumentsContract.isDocumentUri(getActivity(), uri)) {// 如果是document类型的Uri,则通过document id处理val docId = DocumentsContract.getDocumentId(uri)if ("com.android.providers.media.documents" == uri!!.authority) {val id = docId.split(":".toRegex()).toTypedArray()[1] // 解析出数字格式的idval selection = MediaStore.Images.Media._ID + "=" + idimagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection)} else if ("com.android.providers.downloads.documents" == uri.authority) {val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(docId))imagePath = getImagePath(contentUri, null)}} else if ("content".equals(uri!!.scheme, ignoreCase = true)) {// 如果是content类型的Uri,则使用普通方式处理imagePath = getImagePath(uri, null)} else if ("file".equals(uri.scheme, ignoreCase = true)) {// 如果是file类型的Uri,直接获取图片路径即可imagePath = uri.path}displayImage(imagePath) // 根据图片路径显示图片}private fun handleImageBeforeKitKat(data: Intent) {val uri = data.dataval imagePath = getImagePath(uri, null)displayImage(imagePath)}fun openAlbum() {val intent = Intent("android.intent.action.GET_CONTENT")intent.type = "image/*"startActivityForResult(intent, CHOOSE_PHOTO) // 打开相册}override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {when (requestCode) {1 -> if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {openAlbum()} else {myToast("You denied the permission")}}}private fun getImagePath(uri: Uri?, selection: String?): String? {var path: String? = null// 通过Uri和selection来获取真实的图片路径val cursor = getActivity()?.contentResolver?.query(uri!!, null, selection, null, null)if (cursor != null) {if (cursor.moveToFirst()) {path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA))}cursor.close()}goodsimageuristring=pathreturn path}private fun displayImage(imagePath: String?) {if (imagePath != null) {val bitmap = BitmapFactory.decodeFile(imagePath)imageView.setImageBitmap(bitmap)} else {myToast("failed to get image")}}}

class HomeFragment: BaseFragment() {override fun initView(): View? {return View.inflate(context, R.layout.fragment_home, null)}override fun initData() {super.initData()Insert_button.setOnClickListener {var goods:Goods = Goods(1,"充电宝","10",100,1.0f,200,true,null)var  goods1:Goods = Goods(1,"充电宝","10",100,1.0f,200,true,null)goodsdao.insertGoods( goods, goods1)updateView();}/*       Delete_button.setOnClickListener {var word:Word = Word("Word","世界")word.setId(40)worddao.deleteWords(word)updateView()}*/Deleteall_button.setOnClickListener{goodsdao.deleteAllGoods()updateView()}
/*        Update_button.setOnClickListener {var word:Word = Word("Word","世界")word.setId(40)worddao.updateWords(word)updateView()}*/}fun updateView(){var list:List<Goods> =goodsdao.getAllGoods()var text=""for (i in (0 until list.size)){var goods:Goods =list.get(i)text+=""+goods.goodsname+goods.goodsprice;}Text_goodsname.text=text}}

4. 首页进行列表显示

  1. 建立adapter

class GoodsAdapter: ListAdapter<Goods,GoodsAdapter.MyViewHolder>(DIFFCALLBACK)  {class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)object DIFFCALLBACK : DiffUtil.ItemCallback<Goods>() {override fun areItemsTheSame(oldItem: Goods, newItem: Goods): Boolean {return oldItem === newItem //判断是否为同一个对象 三等于号}override fun areContentsTheSame(oldItem: Goods, newItem: Goods): Boolean {return oldItem.id == newItem.id//判断内容是否相同}}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {//创建holderval holder = MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.goods_cell, parent, false))return holder}override fun onBindViewHolder(holder: MyViewHolder, position: Int) {val photoItem=getItem(position)//使用with语句with(holder.itemView) {shimmerLayoutCell.apply {setShimmerColor(0x55FFFFFF)setShimmerAngle(0)//闪动角度startShimmerAnimation()}textViewUser.text=photoItem.goodsnametextViewLikes.text="¥${photoItem.goodsprice}"textViewFavorites.text="打折:${photoItem.goodspricecount}"textViewFavorites2.text="存货:${photoItem.goodssum}"textViewFavorites4.text="种别码:${photoItem.goodscode}"textViewFavorites5.text="id:${photoItem.id}"}Glide.with(holder.itemView).load(getItem(position).goodsimageuri)//photo对象.placeholder(R.drawable.photo_placeholder).listener(object : RequestListener<Drawable> {override fun onResourceReady(resource: Drawable?,model: Any?,target: Target<Drawable>?,dataSource: DataSource?,isFirstResource: Boolean): Boolean {return false.also { holder.itemView.shimmerLayoutCell?.stopShimmerAnimation() }//判断空, 图片未加载完全就切走 但listenrer还在监听}override fun onLoadFailed(e: GlideException?,model: Any?,target: com.bumptech.glide.request.target.Target<Drawable>?,isFirstResource: Boolean): Boolean {return false//都return false 不然不显图}//监听加载完成后停止shimmer}).into(holder.itemView.imageView)//加载上去}}
  1. 设置数据源

class HomeFragment: BaseFragment() {override fun initView(): View? {return View.inflate(context, R.layout.fragment_home, null)}override fun initData() {super.initData()var list:List<Goods> =goodsdao.getAllGoods()val goodsAdapter = GoodsAdapter()recycleView.apply{adapter=goodsAdapterlayoutManager= GridLayoutManager(requireContext(),2)//两列}goodsAdapter.submitList(list)}}
  1. sharePerfence储存

class MyData(private val context: Context) {val memoryname by lazy { context.resources.getString(R.string.Login_state) }val itemmemory by lazy{ context.getSharedPreferences(memoryname,Context.MODE_PRIVATE)}val deafultbool by lazy { context.resources.getBoolean(R.bool.default_bool) }var defaultboolvalue=falsefun saveSlash( slash: Boolean){Thread {itemmemory.edit().putBoolean("slashs",slash).apply()}.start()}fun loadSlash():Boolean{defaultboolvalue =itemmemory.getBoolean("slashs",deafultbool)return defaultboolvalue}
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
还有第二个地图定位,就不暴露位置了emmmm。

5. 补充

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

这篇关于【Kotlin-JetPack】融合组件(登录注册,bottombar)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/385252

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

韦季李输入法_输入法和鼠标的深度融合

在数字化输入的新纪元,传统键盘输入方式正悄然进化。以往,面对实体键盘,我们常需目光游离于屏幕与键盘之间,以确认指尖下的精准位置。而屏幕键盘虽直观可见,却常因占据屏幕空间,迫使我们在操作与视野间做出妥协,频繁调整布局以兼顾输入与界面浏览。 幸而,韦季李输入法的横空出世,彻底颠覆了这一现状。它不仅对输入界面进行了革命性的重构,更巧妙地将鼠标这一传统外设融入其中,开创了一种前所未有的交互体验。 想象

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

vue2 组件通信

props + emits props:用于接收父组件传递给子组件的数据。可以定义期望从父组件接收的数据结构和类型。‘子组件不可更改该数据’emits:用于定义组件可以向父组件发出的事件。这允许父组件监听子组件的事件并作出响应。(比如数据更新) props检查属性 属性名类型描述默认值typeFunction指定 prop 应该是什么类型,如 String, Number, Boolean,

kubelet组件的启动流程源码分析

概述 摘要: 本文将总结kubelet的作用以及原理,在有一定基础认识的前提下,通过阅读kubelet源码,对kubelet组件的启动流程进行分析。 正文 kubelet的作用 这里对kubelet的作用做一个简单总结。 节点管理 节点的注册 节点状态更新 容器管理(pod生命周期管理) 监听apiserver的容器事件 容器的创建、删除(CRI) 容器的网络的创建与删除

火语言RPA流程组件介绍--浏览网页

🚩【组件功能】:浏览器打开指定网址或本地html文件 配置预览 配置说明 网址URL 支持T或# 默认FLOW输入项 输入需要打开的网址URL 超时时间 支持T或# 打开网页超时时间 执行后后等待时间(ms) 支持T或# 当前组件执行完成后继续等待的时间 UserAgent 支持T或# User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器

vue 父组件调用子组件的方法报错,“TypeError: Cannot read property ‘subDialogRef‘ of undefined“

vue 父组件调用子组件的方法报错,“TypeError: Cannot read property ‘subDialogRef’ of undefined” 最近用vue做的一个界面,引入了一个子组件,在父组件中调用子组件的方法时,报错提示: [Vue warn]: Error in v-on handler: “TypeError: Cannot read property ‘methods