vue2:scoped样式属性、nanoid、记录本小案例(基础版)

简介: vue2:scoped样式属性、nanoid、记录本小案例(基础版)

一、scoped样式属性(局部范围样式)及lang=" "的运用(默认情况下自动选择css,也不会出现lang=""让你选择语言的提示)


scoped样式属性

如果我们给两个子组件中添加的样式类名相同就会出现类名冲突的问题,
        vue显然页面的时候会最终把最后在app.vue中组测的组件的类名中的样式,
        渲染出来!

例如:

LqjSchool.vue:

<template><divclass="School"><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2></div></template>                ...
<style>.School{
background: rgb(23, 190, 241);
                        }
</style>

StudentLqj.vue:

<template><divclass="School"><h2>学生姓名:{{name}}</h2><h2>学生性别:{{msg}}</h2></div></template>                ...
<style>.School{
background: rgb(248, 120, 0);
                        }
</style>

App.vue:

importLqjSchoolfrom'./components/LqjSchool.vue'importStudentLqjfrom'./components/StudentLqj.vue'

注意:LqjSchool.vue中School的背景色为天蓝色
              StudentLqj.vue中School的背景色为橙色


结果:页面中渲染出的文字的背景颜色是StudentLqj.vue中.School的颜色:橙色


image.png

如果我们项避免出现这种情况解决方法:

       1.在不同的子组件中写不同的样式名

       2.给每一个子组件中的<style>添加scoped属性

       例如:<style scoped>   </style>

       这样我们写的样式名即使多个组件都一样,也不会出现冲突!


image.png

scoped样式属性(局部范围样式)

原理:

       原理:当我们用scoped属性来限制样式标签时,在页面渲染时会给用样式的每个<div>中的标签一个随机的id,根据此id来对应限制的标签,从而达到限制局部效果!

image.png

lang=" "的运用

此属性是供开发者在<style>标签中选择样式语言的(以css和less为例)


1.如果开发者想用css来写样式属性:

<stylelang="css"scoped>.School{
background: rgb(23, 190, 241);
                }
</style>

2.如果开发者想用less来写样式属性:

<stylelang="less"scoped>.School{
background: rgb(23, 190, 241);
                }
</style>

注意:默认情况下less是vue编译不了的我们必须借助
        (终端命令:npm i less-loader)才能正常运行。但也有可能报错:

原因你的vue脚手架调用的webpack的版本兼容问题!

image.png

查看webpack版本终端命令中输入:

npm view webpack versions

查看less-loader版本终端命令中输入:

npm view less-loader versions

安装:(我们以7版本为例)

npm i less-loader@7


二、nanoid(类型函数)直接去调用它,就能给出一个唯一的字符串


首先需要安装:

npm i nanoid

它使用分别暴露的形式,所以这样引入:

import {nanoid} from 'nanoid'


举例:

<script>import {nanoid} from'nanoid'exportdefault{
name:'Myheader',
methods:{
add(e){//e事件对象//将用户的输入包装成为一个todos对象constObj= {id:nanoid()}
                        }
                        }
                }
</script>

结果显示:

这个库会随机生成一个id


三、小案例(基础版):

app.vue:

<template><divid="root"><divclass="box"><spanclass="haizei">oen piece,记录本</span></div><divclass="todo-container"><divclass="todo-wrap"><Myheader:addTodos="addTodos"></Myheader><List:todos="todos":checkTodo="checkTodo":deleteTodo="deleteTodo"></List><Myfooter:todos="todos":checkAllTodo="checkAllTodo":clearAllTodo="clearAllTodo"></Myfooter></div></div></div></template><script>// 引入School组件 importMyheaderfrom'./components/Myheader.vue'importListfrom'./components/List.vue'// 因为List是Item的父组件,所以不用引入Item// import Item from './components/Item.vue'importMyfooterfrom'./components/Myfooter.vue'exportdefault {
name: 'App',
// msg里面要接受到的数据开始components: {Myheader,List,
// Item,Myfooter,},
data(){
return{
todos:JSON.parse(localStorage.getItem('todos')) || []
// todos:[//     // {id:'001',title:'学vue+写csdn',done:true},//     // {id:'002',title:'吃饭',done:false},//     // {id:'003',title:'学高数+四级',done:false}// ]                }
            },
methods:{
//添加一个todoObjaddTodos(Obj){
this.todos.unshift(Obj) 
      },
//勾选或取消勾选todoObjcheckTodo(id){
this.todos.forEach((todoObj)=>{
//函数体if(todoObj.id===id)  todoObj.done=!todoObj.done        })
      },
//删除一个todoObjdeleteTodo(id){
this.todos=this.todos.filter((todoObj)=>{
returntodoObj.id!==id        })
      },
//全选or全不选checkAllTodo(done){
this.todos.forEach((todoObj)=>{
todoObj.done=done        })
      },
//清除所有已经完成的todosclearAllTodo(){
this.todos=this.todos.filter((todoObj)=>{
return!todoObj.done        })
      }
    },
watch:{
todos:{
deep:true,
handler(value){
localStorage.setItem('todos',JSON.stringify(value))
        }
      }
    }
}
</script><style>/*base*/body {
background-image: url(../src/assets/1.png) ;
Opacity:1}
.btn {
display: inline-block;
padding: 4px12px;
margin-bottom: 0;
font-size: 14px;
line-height: 20px;
text-align: center;
vertical-align: middle;
cursor: pointer;
box-shadow: inset01px0rgba(0, 255, 64, 0.2), 01px2pxrgba(11, 88, 255, 0.05);
border-radius: 4px;
}
.btn-danger {
color: #fff;
background-color: #1cda45;
border: 1pxsolid#0d8fe6;
}
.btn-danger:hover {
color: #fff;
background-color: #f70ea9;
}
.btn:focus {
outline: none;
}
.todo-container {
width: 600px;
margin: 0auto;
}
.todo-container.todo-wrap {
padding: 10px;
border: 1pxsolidrgb(250, 150, 0);
border-radius: 5px;
}
.box{
display: flex;
flex-direction: row;
justify-content: space-around;
}
.haizei{
font-size: 50px;
color: rgb(245, 147, 0);
font-weight: 800;
}
</style>

Item.vue:

<template><li><label><inputtype="checkbox":checked="todoObj.done"@change="handleCheck(todoObj.id)"/><!-- <input type="checkbox" v-model="todo.done"></input> --><spanclass="ziti">{{todoObj.title}}</span><!-- <span>{{todoObj.done}}</span> --></label><buttonclass="btn btn-danger"@click="handleDelete(todoObj.id)">删除</button></li></template><script>exportdefault{
name:'Item',
//生命接受todoObj对象props:['todoObj','checkTodo','deleteTodo'],
methods:{
//勾选or取消勾选handleCheck(id){
//通知App组件将对应的todo对象done值取反this.checkTodo(id)
            },
//删除handleDelete(id){
//通知App组件将对应的todo对象done值取反if(confirm('确定删除吗?')){
this.deleteTodo(id)
                }
            },
        }
    }
</script><stylescoped>/*item*/li {
list-style: none;
height: 36px;
line-height: 36px;
padding: 05px;
border-bottom: 1pxsolid#ddd;
}
lilabel {
float: left;
cursor: pointer;
}
lilabelliinput {
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
libutton {
float: right;
display: none;
margin-top: 3px;
}
li:before {
content: initial;
}
li:last-child {
border-bottom: none;
}
li:hover{
background: rgb(129, 3, 247);
}
li:hoverbutton{
display: block;
}
.ziti{
font-size: 15px;
color: aliceblue;
}
</style>

Myfooter.vue:

<template><divclass="todo-footer"v-show="total"><label><inputtype="checkbox":checked="isAll"@change="checkAll"/></label><spanclass="wenzi"><span>已完成{{doneTotal}}</span> / 全部{{total}}
</span><buttonclass="btn btn-danger"@click="clearAll">清除已完成任务</button></div></template><script>exportdefault{
name:'Myfooter',
props:['todos','checkAllTodo','clearAllTodo'],
computed:{
total(){
returnthis.todos.length          },
doneTotal(){
// let i = 0// this.todos.forEach((todoObj)=>{//   if(todoObj.done) i++// })// return i returnthis.todos.reduce((pre,todoObj)=>pre+ (todoObj.done?1 : 0),0)
          },
isAll(){
returnthis.doneTotal===this.total&&this.total>0          }
        },
methods:{
checkAll(e){
this.checkAllTodo(e.target.checked)
          },
clearAll(){
this.clearAllTodo()
          }
        }
    }
</script><stylescoped>/*footer*/.todo-footer {
height: 40px;
line-height: 40px;
padding-left: 6px;
margin-top: 5px;
}
.todo-footerlabel {
display: inline-block;
margin-right: 20px;
cursor: pointer;
}
.todo-footerlabelinput {
position: relative;
top: -1px;
vertical-align: middle;
margin-right: 5px;
}
.todo-footerbutton {
float: right;
margin-top: 5px;
}
.wenzi{
font-size: 20px;
color: azure;
}
</style>

Myheader.vue:

<template><divclass="todo-header"><inputtype="text"placeholder="请输入你的任务名称,按回车键确认"v-model="title"@keyup.enter="add"/></div></template><script>import {nanoid} from'nanoid'exportdefault{
name:'Myheader',
props:['addTodos'],
data(){
return{
title:''            }
        },
methods:{
add(){
//校验数据if(!this.title.trim()) returnalert('输入不能为空')
//将用户的输入包装成为一个todos对象constObj= {id:nanoid(),title:this.title,done:false}
//通知app组件去添加一个todos对象this.addTodos(Obj)
//清空输入框的内容this.title=" "            }
        }
    }
</script><stylescoped>/*header*/.todo-headerinput {
width: 560px;
height: 28px;
font-size: 14px;
border: 1pxsolid#ccc;
border-radius: 4px;
padding: 4px7px;
}
.todo-headerinput:focus {
outline: none;
border-color: rgba(82, 168, 236, 0.8);
box-shadow: inset01px1pxrgba(0, 0, 0, 0.075), 008pxrgba(82, 168, 236, 0.6);
}
</style>

image.png

oen piece是真是存在的!!!

目录
相关文章
|
2月前
|
JavaScript API
Vue3中的计算属性能否动态修改
【9月更文挑战第5天】Vue3中的计算属性能否动态修改
241 10
|
7天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
1月前
|
JavaScript API
vue尚品汇商城项目-day04【24.点击搜索按钮跳转后的页面商品列表、平台售卖属性动态展示(开发Search组件)】
vue尚品汇商城项目-day04【24.点击搜索按钮跳转后的页面商品列表、平台售卖属性动态展示(开发Search组件)】
53 1
vue尚品汇商城项目-day04【24.点击搜索按钮跳转后的页面商品列表、平台售卖属性动态展示(开发Search组件)】
|
1月前
|
监控 JavaScript 开发者
在 Vue 中,子组件为何不可以修改父组件传递的 Prop,如果修改了,Vue 是如何监控到属性的修改并给出警告的
在 Vue 中,子组件不能直接修改父组件传递的 Prop,以确保数据流的单向性和可预测性。如果子组件尝试修改 Prop,Vue 会通过响应式系统检测到这一变化,并在控制台发出警告,提示开发者避免这种操作。
|
2月前
|
缓存 JavaScript 前端开发
vue-day02计算属性,v-bind,v-if,v-for
文章介绍了Vue.js中的计算属性、class与style的绑定、条件渲染和列表渲染的使用。通过示例代码展示了如何使用计算属性简化模板逻辑、如何通过v-bind动态绑定class和style、如何使用v-if进行条件渲染以及如何使用v-for进行列表渲染。这些特性使得Vue.js在构建动态用户界面时更加灵活和强大。
vue-day02计算属性,v-bind,v-if,v-for
|
1月前
|
JavaScript 前端开发 开发者
VUE学习一:初识VUE、指令、动态绑定、计算属性
这篇文章主要介绍了Vue.js的基础知识,包括初识Vue、指令如v-for、v-on的使用、动态属性绑定(v-bind)、计算属性等概念与实践示例。
61 1
|
1月前
|
缓存 JavaScript 前端开发
探索Vue.js中的计算属性与侦听器
【10月更文挑战第5天】探索Vue.js中的计算属性与侦听器
22 1
|
1月前
|
缓存 JavaScript
|
1月前
|
缓存 JavaScript Serverless
vue中computed计算属性、watch侦听器、methods方法的区别以及用法
vue中computed计算属性、watch侦听器、methods方法的区别以及用法
103 0
|
2月前
|
JavaScript
vue 计算属性,实现复选框的全选和反选 【小案例】
本文通过一个Vue.js小案例,展示了如何使用计算属性实现复选框的全选和反选功能。计算属性的完整写法包括get和set两部分,分别用于获取值和设置值。在全选和反选的场景中,计算属性的get方法用于判断所有复选框是否都已选中,从而控制全选复选框的状态;计算属性的set方法则用于根据全选复选框的状态,批量更新每个复选框的选中状态。通过示例代码和效果图,文章清晰地说明了计算属性在实现这一功能中的作用和效果。
vue 计算属性,实现复选框的全选和反选 【小案例】