一、 Vue3中集成sass/scss

1.1 安装sass-loader node-sass

# 这也安装的话,会导致版本过高出现问题
npm install -D sass-loader node-sass# 推荐安装这个
npm install sass-loader@5.0.0 node-sass@4.14.1

1.2 style中配置sass/scss

lang可以配置scss,scoped表示这里写的css只有当前组件有效

<template><h2>Vue实现TodoList</h2><div class="todolist"><h3>todolist</h3></div>
</template><style lang="scss" scoped>h2 {text-align: center;}.todolist {width: 500px;border: 1px solid #eeeeee;margin: 0 auto;padding: 20px;h3 {color: red;font-size: 40px;}}
</style>

1.3 案例 实现TodoList

<template><h2>Vue实现TodoList</h2><div class="todolist"><!--  @keyup.enter 表示按下enter进行触发 @表示v-on 触发时间      --><input type="text" v-model="todo" @keyup.enter="addData()" placeholder="请输入待办事项"><h4>正在进行</h4><ul><!-- 通过template 解决v-for 和 v-if一起使用 --><template v-for="(item, index) in dataList" :key="index"><li v-if="!item.checked"><!--复选框 当checked为true是表示选中  @change 监听该input发生改变时触发--><input type="checkbox" v-model="item.checked" @change="setTodoList()"> {{item.title}} ----<button @click="deleteData(index)">删除</button></li></template></ul><h4>已经完成</h4><ul><!-- v-for 和 v-show 一起使用 --><li v-for="(item, index) in dataList" :key="index" v-show="item.checked"><!--复选框 当checked为true是表示选中 --><input type="checkbox" v-model="item.checked" @change="setTodoList()"> {{item.title}} ----<button @click="deleteData(index)">删除</button></li></ul><pre>{{dataList}}</pre></div></template><script>import storage from './modules/storage'export default {data() {return {todo: "",dataList: []}},methods: {addData() {this.dataList.push({"title": this.todo,"checked": false});this.todo = "";storage.set("todo", this.dataList);},deleteData(index) {// 根据索引来删除list里的数据,并且删除一个this.dataList.splice(index, 1);storage.set("todo", this.dataList);},setTodoList() {storage.set("todo", this.dataList);}},// 页面加载的时候触发的方法mounted() {let todo = storage.get("todo");if (todo) {this.dataList = todo;}console.log("页面加载的时候触发的方法");}}
</script><style lang="scss" scoped>h2 {text-align: center;}.todolist {width: 500px;border: 1px solid #eeeeee;margin: 0 auto;padding: 20px;h3 {color: red;font-size: 40px;}}
</style>
src/modules/storage.js
const storage = {set(key, value) {localStorage.setItem(key, JSON.stringify(value));},get(key) {return JSON.parse(localStorage.getItem(key));},remove(key) {localStorage.removeItem(key);}
};// 导出去,可以让其它文件使用
export default storage

二、组件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T3CIK8OV-1630392500752)(./images/vue组件.png)]

2.1 组件使用步骤

  1. 创建组件 : 在src/components/下创建首页组件Home.vue

  2. 引入组件 : 在App.vue 下引入组件 import Home from “./components/Home”;

    <script>// 1.引入组件import Home from "./components/Home";export default {data() {return {msg: "App根组件"}},// 2.注册组件components: {Home}}
    </script>
    
  3. 注册组件 : 在App.vue 下注册组件 :

    components: {Home
    }
    
  4. 使用组件: 在App.vue下使用组件

    <template><h2>{{msg}}</h2><hr><!--3.使用组件--><Home/>
    </template>
    

2.2 使用组件

Header.vue
<template><header>我是一个头部组件</header>
</template><script>export default {name: "Header"}
</script><style scoped>header {width: 100%;height: 44px;text-align: center;line-height: 44px;background: #000;color: #fff;}</style>
Home.vue
<template><!--使用头部组件--><v-header/><h5>{{title}}</h5><button @click="getTitle()">点击</button></template><script>// 引入头部组件import Header from "./Header";export default {name: "Home",data() {return {title: "首页组件"}},methods: {getTitle() {alert(this.title)}},// 注册组件components: {// 给组件起一个别名"v-header": Header}}
</script><style lang="scss" scoped>h5 {text-align: center;}
</style>
App.vue
<template><!--3.使用组件--><Home/>
</template><script>// 1.引入组件import Home from "./components/Home";export default {data() {return {msg: "App根组件"}},// 2.挂载组件components: {Home}}
</script><!-- scoped 表示css是一个局部作用域-->
<style lang="scss" scoped>h2 {text-align: center;}
</style>

2.3 父组件传值给子组件

父组件里传递数据
<template><!--使用头部组件传递数据 key=value  可以把该父组件的数据以及方法都传过去--> <v-header :title="title" :msg="'我是父组件msg'" :home="this"/>
</template>...data() {return {title: "首页"}},methods: {getTitle() {alert(this.title)}}
子组件里接受数据
<template>{{title}}<hr>{{msg}}
</template> export default {name: "Header",props: ["title", "msg"]  // 接受父组件传递的值,和父组件传递的key保持一致}props:校验props:{title: String  // 表示父组件传递过来的title必须为string
}
单向数据流

所有的prop都使得其父子prop之间形成了一个单向下行绑定:父级prop的更新会向下流动到子组件中,但是反过来则不行。这也会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

另外,每次父级组件发生变更时,子组件中所有的prop都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变prop。如果你这样做了,Vue会在浏览器的控制台中发出警告。

2.4 父组件主动获取子组件的数据和执行子组件方法

调用子组件的时候定义一个ref
<v-header ref="header"></v-header>
父组件主动获取子组件数据
this.$refs.header.属性
父组件主动执行子组件方法
this.$refs.header.方法

2.5 子组件主动获取父组件的数据和执行父组件方法

子组件主动获取父组件的数据
this.$parent.数据
子组件主动获取父组件的数据
this.$parent.方法

2.6 父子组件自定义事件进行传值(emit)

主要作用:子组件给父组件传值,子组件调用父组件里的方法

使用步骤
  1. 父组件里自定义事件
  2. 子组件里调用父组件的定义的事件
父组件定义自定事件
**Home.vue **父组件
<template><!--使用头部组件 自定义事件send 触发send事件 执行getChild方法--><v-header @send="getChild"/>
</template><script>// 引入头部组件import Header from "./Header";export default {name: "Home",data() {return {title: "首页"}},methods: {getChild(data) {alert(this.title + "home " + data);}},// 注册组件components: {// 给组件起一个别名"v-header": Header}}
</script><style lang="scss" scoped>h5 {text-align: center;}
</style>
子组件里调用父组件自定义事件
**Header.vue **子组件
<template><header>我是一个头部组件</header><!-- 点击按钮执行方法 --><button @click="sendParent()">执行父组件里的方法</button>
</template><script>export default {// 建议定义出所有发出的自定义事件,以便更好记录组件应该如何工作emits: ["send"],name: "Header",methods: {sendParent() {// 触发父组件里的send事件this.$emit("send", "hello world");}}}
</script><style scoped>header {width: 100%;height: 44px;text-align: center;line-height: 44px;background: #000;color: #fff;}
</style>
验证触发事件里的数据
Home.vue 父组件
<template><!--使用头部组件 自定义事件 send 触发send事件执行getChild方法--><v-header @send="getChild"/><!--自定义事件 submit 触发send事件执行doLogin方法--><v-login @submit="doLogin"></v-login>
</template><script>// 引入头部组件import Header from "./Header";import Login from "./Login";export default {name: "Home",data() {return {title: "首页"}},methods: {getChild(data) {alert(this.title + "home " + data);},doLogin(data) {console.log(data)}},// 注册组件components: {// 给组件起一个别名"v-header": Header,"v-login": Login}}
</script><style lang="scss" scoped>h5 {text-align: center;}
</style>
Login.vue 子组件
<template><div class="login"><input type="text" v-model="username" placeholder="用户名"/><br><input type="text" v-model="password" placeholder="密码"/><br><button @click="doLogin()">执行登录</button></div>
</template><script>export default {name: "Login",// 验证自定义事件 submitemits: {submit: ({username, password}) => {if (username != "" && password != "") {return true} else {console.error("用户名或密码不能为空");alert("用户名或密码不能为空");return false}}},data() {return {username: "",password: ""}},methods: {doLogin() {this.$emit("submit", {username: this.username,password: this.password})}}}
</script><style scoped>.login {padding: 20px;}
</style>

2.7 非父子组件自定义事件进行传值(mitt)

使用步骤
  1. 安装mitt
  2. 创建event.js
  3. 在一个组件(login)里 定义监听事件
  4. 另一个组件(header)里 触发该事件
安装mitt
npm install --save mitt
创建 src/model/event.js
import mitt from "mitt";const event = mitt();export default event;
Login.vue
<template><div class="login"><input type="text" v-model="username" placeholder="用户名"/><br><input type="text" v-model="password" placeholder="密码"/><br><button @click="doLogin()">执行登录</button></div>
</template><script>// 引入eventimport event from "../models/event";export default {name: "Login",data() {return {username: "",password: ""}},mounted() {// 监听在这里自定义事件 toLoginevent.on("toLogin", (data) => {console.log(data);})}}
</script><style scoped>.login {padding: 20px;}
</style>
Header.vue
<template><header>我是一个头部组件</header><button @click="sendLogin">触发登录组件里的事件 进行传值</button>
</template><script>import event from "../models/event";export default {name: "Header",methods: {sendLogin() {// 调用自定义事件event.emit("toLogin", "头部组件传过来的数据")}}}
</script><style scoped>header {width: 100%;height: 44px;text-align: center;line-height: 44px;background: #000;color: #fff;}
</style>

2.8 自定义组件使用v-mode实现双向数据绑定

使用步骤
  1. 父组件里引入子组件
  2. 修改子组件里的值
单个v-mode数据绑定

默认情况下,组件上的 v-model使用modelValue作为prop和 update:modelValue作为事件。我们可以通过向v-model传递参数来修改这些名称:

<my-component v-model:foo="bar"></my-component>
父组件 Home.vue
<template><div class="home"><h1>我是首页组件</h1><hr><!-- 引入子组件 自定义属性名aaa--><AcInput v-model:a1="keyword1" v-model:a2="keyword2"></AcInput><br>首页组件: {{keyword1}} --- {{keyword2}}</div></template><script>import AcInput from "./AcInput";export default {name: "Home",data() {return {keyword1: "女装",keyword2: "男装",}},components: {AcInput}}
</script><style lang="scss" scoped>.home {padding: 20px;}
</style>
子组件 AcInput.vue
<template><!-- 修改该input值时,同时修改父组件里的值    @input-->子组件:<input type="text" :value="a1" @input="$emit('update:a1', $event.target.value)" placeholder="请输入内容"><br>子组件:<input type="text" :value="a2" @input="$emit('update:a2', $event.target.value)" placeholder="请输入内容">
</template><script>export default {name: "AcInput",data() {return {}},// 接受父组件传过来属性props: ["a1", "a2"]}
</script><style lang="scss" scoped>input {width: 400px;height: 42px;line-height: 42px;}
</style>

2.9 slot用法

作用:可以服用同一个按钮,显示的结果不一样

使用步骤
  1. 在子组件里button中引入slot
  2. 在父组件里调用子组件,在引用子组件时,传递数据(html 字符串等等)
子组件 AcButton.vue
<template><button class="default"><!-- 默认值为“按钮”,当父组件调用时,传递值时,默认值就会被替换掉--><slot>按钮</slot></button>
</template><script>export default {name: "AcButton"}
</script><style scoped>.default {padding: 5px 10px;background: orange;color: #ffffff;border: none;}.primary {padding: 5px 10px;background: blue;color: #ffffff;border: none;}.black {padding: 5px 10px;background: black;color: #ffffff;border: none;}
</style>
父组件 Home.vue
<template><div class="home"><h1>我是首页组件</h1><hr><!-- 引用子组件 子组件里的slot会接收“提交”; 给子组件传递属性class,子组件里的根标签会接收到class的属性--><v-button class="primary">提交</v-button><hr><v-button><i>Icon</i> 确认</v-button><hr><v-button class="black"></v-button></div></template><script>import AcButton from "./AcButton";export default {name: "Home",data() {return {}},components: {"v-button": AcButton}}
</script><style lang="scss" scoped>.home {padding: 20px;}
</style>

2.10 自定义属性

子组件 DataPicker.vue
<template><div class="data-picker"><!-- 表示该标签 继承父组件传过来的属性 v-bind="$attrs"--><input type="date" v-bind="$attrs"/></div>
</template><script>export default {name: "DataPicker",inheritAttrs: false,  // 禁用默认集成,默认是根标签继承 父组件传过来的属性,改为false,表示禁用}
</script><style scoped>
</style>
父组件 Home.vue
<template><div class="home"><h1>我是首页组件</h1><hr><!--调用子组件 传递属性 date-time过去--><DataPicker date-time="2021-08-01"></DataPicker></div></template><script>import DataPicker from "./DataPicker";export default {name: "Home",data() {return {}},components: {DataPicker}}
</script><style lang="scss" scoped>.home {padding: 20px;}
</style>

3 生命周期

父组件 Home.vue

<template><div class="home"><h1>我是首页组件</h1><hr><button @click="isShow=!isShow">挂载/卸载组件</button><LifeCycle v-if="isShow"></LifeCycle></div></template><script>import LifeCycle from "./LifeCycle";export default {name: "Home",data() {return {isShow: true}},components: {LifeCycle}}
</script><style lang="scss" scoped>.home {padding: 20px;}
</style>

子组件 LifeCycle.vue

<template><br><button @click="msg='修改后的数据'">修改数据</button><h1>{{msg}}</h1></template><script>export default {name: "LifeCycle",data() {return {msg: "我是一个数据",}},// 属性页面时触发:beforeCreate created beforeMount mountedbeforeCreate() {console.log("实例刚刚被创建1");},created() {console.log("实例已经创建完成2");},beforeMount() {console.log("模板编译之前3");},mounted() {// 请求数据,操作dom,放在这个里面console.log("模板编译完成4");},// 修改数据时触发:beforeUpdate updatedbeforeUpdate() {console.log("数据更新之前");},updated() {console.log("数据更新完毕");},activated() {console.log("keep-alive 缓存的组件激活时调用");},deactivated() {console.log("keep-alive 缓存的组件停用时调用");},// 干掉组件时(通过v-if) 触发:beforeUnmount  unmountedbeforeUnmount() {console.log("实例销毁之前");},unmounted() {console.log("实例销毁之后");}}
</script><style scoped></style>

动态组件keep-alive的使用

作用:缓存子组件里的内容

父组件 Home.vue
<template><div class="home"><h1>我是首页组件</h1><hr><button @click="isShow=!isShow">挂载/卸载组件</button><!-- 缓存组件 --><keep-alive><LifeCycle v-if="isShow"></LifeCycle></keep-alive></div></template><script>import LifeCycle from "./LifeCycle";export default {name: "Home",data() {return {isShow: true}},components: {LifeCycle}}
</script><style lang="scss" scoped>.home {padding: 20px;}
</style>
子组件 LifeCycle.vue
<template><br><button @click="msg='修改后的数据'">修改数据</button><h1>{{msg}}</h1><hr><div class="tab_info"><ul class="tab_header"><!-- :class 可以控制添加选择器 添加样试 --><li v-for="(item, index) in posts" :class="{active: currentIndex===index}" :key="index"@click="currentIndex=index">{{item.title}}</li></ul><div class="tab_content"><span v-html="contentByIndex"></span></div></div></template><script>export default {name: "LifeCycle",data() {return {currentIndex: 0,msg: "我是一个数据",posts: [{"id": 1,"title": "nodejs教程","content": "<p>nodejs教程很不错呀</p>"},{"id": 2,"title": "Java教程","content": "<p>Java教程很不错呀</p>"},{"id": 3,"title": "Python教程","content": "<p>Python教程很不错呀</p>"},],}},computed: {contentByIndex() {return this.posts[this.currentIndex].content;}},// 属性页面时触发:beforeCreate created beforeMount mountedbeforeCreate() {console.log("实例刚刚被创建1");},created() {console.log("实例已经创建完成2");},beforeMount() {console.log("模板编译之前3");},mounted() {// 请求数据,操作dom,放在这个里面console.log("模板编译完成4");},// 修改数据时触发:beforeUpdate updatedbeforeUpdate() {console.log("数据更新之前");},updated() {console.log("数据更新完毕");},activated() {console.log("keep-alive 缓存的组件激活时调用");},deactivated() {console.log("keep-alive 缓存的组件停用时调用");},// 干掉组件时(通过v-if) 触发:beforeUnmount  unmountedbeforeUnmount() {console.log("实例销毁之前");},unmounted() {console.log("实例销毁之后");}}
</script><style lang="scss" scoped>.tab_info {width: 600px;margin: 0 auto;border: 1px solid #eeeeee;ul {list-style: none;}.tab_header {width: 100%;height: 40px;line-height: 40px;li {display: inline-block;margin: 0px 5px;background: #eeeeee;text-align: center;padding: 0px 10px;/* 鼠标放上去变成小手指*/cursor: pointer;/* 在li上添加active的样试 */&.active {background: red;color: #eeeeee;}}}.tab_content {padding: 40px;}}
</style>

this.$nextTick

作用:仅在渲染整个视图之后运行的代码,可以获取最新的html内容

<template><br><button @click="msg='修改后的数据'" ref="btn01">修改数据</button><div id="msg">{{msg}}</div></template><script>export default {name: "Next",data() {return {currentIndex: 0,msg: "我是一个数据",}},mounted() {// 获取id选择器let oDiv1 = document.querySelector("#msg");// 获取标签里的内容console.log("1-" + oDiv1.innerHTML);  //结果:我是一个数据this.msg = "$nextTick演示";let oDiv2 = document.querySelector("#msg");console.log("2-" + oDiv2.innerHTML);  // 结果:我是一个数据this.$nextTick(() => {// 仅在渲染整个视图之后运行的代码let oDiv3 = document.querySelector("#msg");this.$refs.btn01;  // 获取属性console.log("3-" + oDiv3.innerHTML); // 结果:$nextTick演示});},}
</script><style lang="scss" scoped></style>

04 vue3 scss 组件component kepp-alive缓存子组件 nextTick相关推荐

  1. vue3没了$children,如何获取子组件???

    vue3没了$children,如何获取子组件??? $children 移除 概览 $children 实例 property 已从 Vue 3.0 中移除,不再支持. 2.x 语法 在 2.x 中 ...

  2. vue 父循环怎么拿子循环中的值_Vue 父组件循环使用refs调用子组件方法出现undefined的问题...

    Vue 父组件循环使用refs调用子组件方法出现undefined的问题 1. 背景 最近前端项目遇到一个问题,我在父组件中使用了两个相同的子组件child,分别设置ref为add和update.其中 ...

  3. vue 父组件获取接口值传到子组件_vue 项目中 “父组件” 异步获取数据之后,传递给子组件不显示...

    有两个组件:一个为 transaction(父组件),一个为 transactionList (子组件): 上图为一个列表页,为父组件,在父组件里面的data中定义了数据列表, template中: ...

  4. vue 关于父组件同时多次调用子组件而产生的 this取值 的bug问题

    vue 关于父组件同时多次调用子组件而产生的 this取值 的bug问题 我们在开发vue项目的使用,会经常使用this这个关键字,this指向vue这个实例,我们可以使用this.来获取data里面 ...

  5. vue 组件间的通信,子组件向父组件传值的方式总结

    写vue,如果页面涉及到多个组件,就会涉及组件之间的通信,可能是父子组件间的通信,也可以是同级组件间的通信,那么,vue里面的组件如何通信.一般来说在vue的数据传递是在父组件传子组件通过属性来传,子 ...

  6. vue3 父组件获取数据传值给子组件,子组件有值,但是不渲染

    问题所在就在于,父组件异步获取数据,传给子组件时候,子组件可能已经渲染出来了,所以数据虽然获取到了,但是并没有渲染. 父组件: 1.从接口获取数据 const annular2 = reactive( ...

  7. vue --- 全局注册子组件,并导入全局的子组件

    假设: 需要一个评论的模块comment 由于comment在多个页面中可能会复用. 于是创建一个comment.vue 步骤: 创建comment.vue 在需要引用的位置使import comme ...

  8. vue父组件ajax改变数据,vue父组件传了变量给子组件,改变子组件的对象时,父组件也跟着改变...

    1.问题场景 首先我在父页面引用了一个子组件,当点击的时候我会传值给子组件 showItem(stepJsonItem: any) { var viewDlg = this.$refs.viewIte ...

  9. mysql server 组件cve_Oracle MySQL Server 'Server'子组件远程安全漏洞(CVE-2012-0574)

    发布日期:2013-01-15 更新日期:2013-01-17 受影响系统: Oracle MySQL Server <= 5.5.28 Oracle MySQL Server <= 5. ...

最新文章

  1. Linux Centos 7 安装配置nginx
  2. HALCON查找圆心
  3. accept系统调用内核实现
  4. JS开源框架Stimulus:让web应用在移动端达到原生体验!
  5. mediastream2使用指南(转载)
  6. 2020,你收获了什么?又失去了什么?
  7. apache访问快捷方式
  8. 0分配不到地址_图解 Go 内存分配器
  9. 计算机博士英语复试题目,【转载】考博英语复试纯干货,请务必收藏!
  10. 引用springboot starter 的springboot项目无法引用 springboot starter依赖的项目中的类
  11. 2014年最新前端开发面试题(题目列表+答案 完整版)
  12. ajax.net 的使用方法--摘自网上
  13. Python和R语言之间的详细对比
  14. SPSS学习(三)可靠性(用α系数衡量)
  15. php 对账单系统,PHP实现微信对账单处理
  16. Aho - Corasick string matching algorithm
  17. 西湖论剑2020-BrokenSystems
  18. 实体与实体之间的联系
  19. 电阻电路的等效变化(Ⅱ)
  20. TZT1306标准模拟应变源

热门文章

  1. 四位电脑故障诊断卡使用说明
  2. 什么是晶圆CMP的ILD?
  3. win10服务器权限修改时间,Win10没有权限修改系统时间如何解决?
  4. 软工1816 · 作业(十一)事后诸葛亮
  5. 让ChatGPT来制作Excel表格,ChatGPT实现文本和表格的相互转换
  6. 2021年全国职业院校技能大赛 “大数据技术与应用”—模拟赛题(三)
  7. c语言成绩报告单评语,期末成绩报告单评语
  8. 流行音乐表明我们的注意力越来越短
  9. 一小时建立终生受用的阅读操作系统-笔记
  10. DBeaver 环境配置