组件样式 scoped 和 /deep/ 加scoped 后不会修改其他组件的 加/deep/ 后就可以修改组件内部的 加!important 强制优先级最高覆盖样式 */
<style scoped>
/* 加scoped 后不会修改其他组件的
加/deep/ 后就可以修改组件内部的 加!important 强制优先级最高覆盖样式 */
/deep/.el-pager li.active {
background-color: red !important;
}
</style>
id来找下标,防止待办事件的下标bug (点击未生效)
filter 筛选出不一样的并返回需要的
分割组件vuex 在index.js导入组件(todos.js (为导出组件))
index.js
import axios from 'axios'
import Vue from 'vue'
import Vuex from 'vuex'
import todos from './modules/todos'
Vue.use(Vuex)
const store = new Vuex.Store({
// 严格模式下,控制state的修改只能通过mutations来完成
strict: true,
// modules 模块拆分
modules: {
todos
}
})
export default store
和index.js同级 modules/todo.js
export default {
namespaced: true,
state(){
return {
// 全部, 未完成,已完成
conStr:'全部',
list: JSON.parse(localStorage.getItem('todos')) || [
{
id: 100, name: "吃饭", isDone: true },
{
id: 201, name: "睡觉", isDone: false },
{
id: 103, name: "打豆豆", isDone: true }
]
}
},
getters:{
// 根据list和conStr来计算当前要展示的内容
newList(state){
if(state.conStr === '未完成'){
return state.list.filter(it => it.isDone === false)
} else if(state.conStr === '已完成'){
return state.list.filter(it => it.isDone )
} else {
return state.list
}
}
},
mutations: {
// state: 自动获取
// name: 传入的
addTodo(state, name){
console.log(state, name)
// 添加数据
state.list.push({
id: Date.now(),
name,
isDone: false
})
},
// 删除
delTodo(state, id){
// 找到对应的下标
const idx = state.list.findIndex(it => it.id === id)
// 做删除
state.list.splice(idx, 1)
},
// 修改 id 对应元素的 isDone
changeIsDone(state, id){
const idx = state.list.findIndex(it => it.id === id)
console.log('changeIsDone', idx)
// 找到下标为idx的元素,切换它的状态
state.list[idx].isDone = !state.list[idx].isDone
},
// 修改conStr
changeConStr(state, val){
state.conStr = val
},
// 统一修改全部的状态
// val就是要改成的值
changeAllIsDone(state, val){
state.list.forEach(it => it.isDone = val)
}
}
}
TodoFooter.vue
<template>
<footer class="footer">
<span class="todo-count">总计:<strong>{
{
list.length}}</strong></span>
<ul class="filters">
<li @click="change('全部')">
<a :class="{selected: conStr==='全部'}" href="javascript:;" >全部</a>
</li>
<li @click="change('未完成')">
<a :class="{selected: conStr==='未完成'}" href="javascript:;">未完成</a>
</li>
<li @click="change('已完成')">
<a :class="{selected: conStr==='已完成'}" href="javascript:;" >已完成</a>
</li>
</ul>
<button class="clear-completed" @click="$emit('clearDone')">清除已完成</button>
</footer>
</template>
<script>
import {
mapMutations, mapState } from 'vuex'
export default {
computed: {
...mapState('todos', ['conStr', 'list'])
},
methods:{
...mapMutations('todos', ['changeConStr']),
// 点击按钮,执行回调,同时传入参数
change(val){
this.changeConStr(val)
}
}
}
</script>
todoHeader.vue
<template>
<header class="header">
<h1>vuex-todos</h1>
<!-- 控制是否全选 -->
<input
v-model="isAll"
id="toggle-all" class="toggle-all" type="checkbox" >
<label for="toggle-all"></label>
<!-- @keyup.enter 按键修饰符 -->
<input
v-model.trim="name"
class="new-todo"
placeholder="输入任务名称-回车确认"
autofocus
@keyup.enter="add"
/>
</header>
</template>
<script>
import {
mapMutations, mapState } from 'vuex'
export default {
data(){
return {
name: '' // 要做的事
}
},
computed:{
...mapState('todos', ['list']),
isAll:{
get(){
// 根据state.list中是否全部的事项都完成了?
return this.list.every(it => it.isDone)
},
set(val){
console.log(val)
this.changeAllIsDone(val)
}
}
},
methods:{
...mapMutations('todos', ['addTodo', 'changeAllIsDone']),
add(){
console.log(this.name)
if(this.name === '')
return
this.addTodo(this.name)
// this.$store.commit('todos/addTodo', this.name)
}
}
}
</script>
todoMain.vue
<template>
<ul class="todo-list">
<!-- completed: 完成的类名 -->
<li
:class="{'completed': item.isDone}"
v-for="item in newList"
:key="item.id"
>
<!-- v-model="item.isDone" -->
<div class="view">
<input
:checked="item.isDone"
@change="hChange(item.id)"
class="toggle" type="checkbox" />
<label>{
{
item.name}}</label>
<button class="destroy" @click="del(item.id)"></button>
</div>
</li>
</ul>
</template>
<script>
import {
mapMutations, mapGetters } from 'vuex'
export default {
computed:{
...mapGetters('todos', ['newList'])
},
methods: {
...mapMutations('todos', ['delTodo', 'changeIsDone']),
del(id){
// 调用mutation做删除
this.delTodo(id)
},
hChange(id){
console.log('hChange')
// 派发mutation
this.changeIsDone(id)
}
}
}
</script>
from表单校验 elementUl
<template>
<div style="width: 800px">
<h1>表单</h1>
<el-form ref="form" :rules="rules" :model="form" label-width="80px">
<el-form-item label="手机号" prop="username">
<el-input v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="验证码" prop="password">
<el-input
type="password"
v-model="form.password"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
form: {
username: "",
password: "",
},
/* rules: {
username: [
{
required: true,
message: "请输入用户名",
trigger: "blur",
},
],
}, */
rules: {
username: [
// trigger: 什么时候触发验证
{
required: true, message: "请输入手机号", trigger: "blur" },
// pattern : 正则
{
pattern: /^1[345678]\d{
9}$/,
message: "请输入合法的手机号",
trigger: "blur",
},
],
password: [
{
required: true, message: "验证码", trigger: "blur" },
{
min: 6, max: 8, message: "长度为6-8位", trigger: "blur" },
{
validator(_, value, callback) {
//rule采用的规则
//value:被校验的值
//callback是回调函数
// 如果通过了规则检验,就直接调用callback()
// 如果没有通过规则检验,就调用callback(错误对象,在错误对象中说明原因)
// 例如:callback(new Error('错误说明'))
if (value === "123456") {
callback(new Error("密码不能为123456"));
} else {
callback();
}
},
trigger: "blur",
},
],
},
};
},
methods: {
onSubmit() {
console.log("submit!", this.form.username, this.form.password);
if (this.form.name === "") return;
//手动兜底校验
console.log(this.$refs.form);
// this.$refs.form.validate会让表单自动校验一次
//valid就会自动接收校验的结果
this.$refs.form.validate((valid) => {
console.log(valid);
//valid :true false
//为false:表单会有提示消息
});
},
},
};
</script>
运行vue后自动打开谷歌
vue.config.js
const {
defineConfig
} = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
host: 'localhost',
open: true,
port: 8080
},
lintOnSave: false // 关闭eslint
})
表格样式
路由index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
//导入页面
import Table from '../views/01表格.vue'
import Page from '../views/02-分页面.vue'
Vue.use(VueRouter)
const routes = [{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import( /* webpackChunkName: "about" */ '../views/AboutView.vue')
}, {
path: '/table',
name: 'table',
component: Table
}, {
path: '/page',
name: 'page',
component: Page
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
父组件App.vue
<template>
<div id="app">
<!-- <keep-alive></keep-alive>
< component/>
<router-view/>-->
<!-- <el-button>默认按钮</el-button>
<el-button type="primary">主要按钮</el-button>
<el-button type="success">成功按钮</el-button>
<el-button type="info">信息按钮</el-button>
<el-button type="warning">警告按钮</el-button>
<el-button type="danger">危险按钮</el-button>
-->
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>|
<router-link to="/table">Table</router-link>
<router-link to="/page">Page</router-link>
</nav>
<router-view />
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
nav {
padding: 30px;
}
nav a {
font-weight: bold;
color: #2c3e50;
}
nav a.router-link-exact-active {
color: #42b983;
}
</style>
组件
<template>
<!-- :data表格数据 -->
<!-- <el-table></el-table> 默认插槽 -->
<!-- column列 -->
<!--最后一个表格 不要设置宽度width -->
<el-table :data="tableData" style="width: 100%">
<!-- 默认插槽 -->
<el-table-column prop="name" label="姓名" width="180"> </el-table-column>
<el-table-column prop="date" label="日期" width="180"> </el-table-column>
<el-table-column prop="gender" label="性别" width="180"
><template v-slot:="scope">
<!-- v-slot:="scope" 简写#="scope" 对象是scope -->
<!-- 拿到性别 0女 1男 -->
{
{
scope.row.gender === 0 ? "女" : "男" }}
<!-- {
{
fn(scope.row.gender) 简单那一点用三元
row是当前行的数据}} -->
</template>
</el-table-column>
<el-table-column prop="age" label="年龄" width="180"> </el-table-column>
<el-table-column prop="companyLogo" label="图片" width="180">
<!-- <template v-slot:="scope">
<img
:src="scope.row.companyLogo"
:title="scope.row.companyName"
width="100%"
/>
</template> 插槽作用域 动态数据 -->
<template v-slot:="scope">
<img
:src="scope.row.companyLogo"
:title="scope.row.companyName"
width="100%"
/>
</template>
</el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
<el-table-column label="操作">
<!-- 默认的自定义 删掉prpo -->
<el-button type="danger" icon="el-icon-delete" circle></el-button
></el-table-column>
</el-table>
</template>
<script>
export default {
methods: {
fn(scope) {
console.log(scope);
},
},
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
age: "13岁",
companyName: "小米",
companyLogo: "http://s02.mifile.cn/assets/static/image/logo-mi2.png",
address: "上海市普陀区金沙江路 1518 弄",
gender: 0,
},
{
date: "2016-05-04",
name: "小黑",
age: "18岁",
companyName: "京东",
companyLogo: "https://misc.360buyimg.com/lib/img/e/logo-201305-b.png",
address: "上海市普陀区金沙江路 1517 弄",
gender: 0, //女
},
{
date: "2016-05-01",
name: "曦瓜",
age: "137岁",
companyName: "百度",
companyLogo:
"https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png",
address: "上海市普陀区金沙江路 1519 弄",
gender: 1, //男
},
/* {
date: "2016-05-03",
name: "橙紫皮",
age: "134岁",
address: "上海市普陀区金沙江路 1516 弄",
gender: 1,
}, */
],
};
},
};
</script>
<!-- 选上面一段 点shift 在点下面的就可以cv了 -->