<script src="https://unpkg.com/vue@next"></script>

nvm安装node.jsnvm文档手册 - nvm是一个nodejs版本管理工具 - nvm中文网 (uihtm.com)

mixin混入(局部使用)

定义mixin对象

<script>// mixin 混入const mymixin={data(){return {number:2,count:1}},created(){console.log('mymixin created');},methods:{handleClick(){console.log('mymixin click');}}};const app = Vue.createApp({data() {return {number: 1}},mixins:[mymixin],created(){console.log('created');},methods: {handleClick() {console.log('handleClick');},},template: `<div><div>{{number}}</div><div>{{count}}</div><button @click="handleClick">增加</button></div> `});const vm = app.mount('#root');
</script>

说明:组件data,methods优先级高于mixin中data,methods优先级,而生命周期函数先执行mixin里面的,再执行组件里面的

mixin混入(全局使用)

const app = Vue.createApp({data() {return {number: 1}},created(){console.log('created');},methods: {handleClick() {console.log('handleClick');},},template: `<div><div>{{number}}</div><child /><button @click="handleClick">增加</button></div> `});app.mixin({data(){return{number:2,count:1}},created(){console.log('mymixin created');},methods:{handleClick(){console.log('mymixin click');}}})app.component('child',{template:"<div>{{count}}</div>"});const vm = app.mount('#root');

显示自定义属性

默认情况下,组件的属性优先级高于mixin的属性优先级,想要修改的话,必须补充配置合并策略

// mixin 混入const mymixin = {number: 1};const app = Vue.createApp({mixins:[mymixin],number: 2,template: `<div><div>{{this.$options.number}}</div></div> `});app.config.optionMergeStrategies.number=(mixinVal,appValue)=>{return mixinVal||appValue;}const vm = app.mount('#root');

自定义指令(局部和全局)

// 自定义指令 directive// 局部指令// const directives={//     focus:{//         mounted(el){//             el.focus();//         }//     }// }const app=Vue.createApp({data(){return{hello:true}},// directives:directives,template:`<div><div v-show="hello"><input v-focus /></div>    </div>`})// 全局指令app.directive('focus',{beforeMount(el){console.log('beforeMount');},mounted(el){el.focus();console.log('mounted');},// 变化前执行 v-showbeforeUpdate(){console.log('beforeUpdate');},updated(){console.log('updated');},// 销毁前执行 v-ifbeforeUnmount(){console.log('beforeUnmount');},unmounted(){console.log('unmounted');}});const vm = app.mount('#root');

v-pos指令(定位)

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>lesson 29</title><style>.header{position: absolute;}</style><script src="https://unpkg.com/vue@next"></script>
</head><body><div id="root"></div>
</body>
<script>// 自定义指令 directiveconst app=Vue.createApp({data(){return{distance:100}},template:`<div><div v-pos:left="distance" class="header"><input /></div>    </div>`})// 全局指令// app.directive('pos',{//     mounted(el,binding){//         el.style.top=(binding.value+'px');//     },//     updated(el,binding){//         el.style.top=(binding.value+'px');//     }// });// 当只有mounted和updated且里面内容一样时,可以使用箭头函数app.directive('pos',(el,binding)=>{console.log(binding);el.style[binding.arg]=(binding.value+'px');})const vm = app.mount('#root');
</script></html>

传送门teleport

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>lesson 30</title><style>.area {position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);width: 200px;height: 300px;background-color: #000;}.mask {position: absolute;left: 0;right: 0;bottom: 0;top: 0;background: #000;opacity: 0.5;color: #fff;font-size: 100px;}</style><script src="https://unpkg.com/vue@next"></script>
</head><body><div id="root"></div><div id="hello"></div>
</body>
<script>// 传送门 teleportconst app = Vue.createApp({data() {return {show: false,message: 'hello'}},methods: {handleBtnClick() {this.show = !this.show;}},template: `<div class="area"><button @click="handleBtnClick">按钮</button><teleport to="#hello"><div class="mask" v-show="show">{{message}}</div>    </teleport></div>`})const vm = app.mount('#root');
</script></html>

slot插槽

const app = Vue.createApp({template: `<my-title>hello</my-title>`});app.component('my-title',{template:`<h1><slot/></h1>  `})const vm = app.mount('#root');

render函数(难底层) 选修课

作用形式:template -> render -> h -> 虚拟DOM(JS对象) -> 真实DOM -> 展示到页面上

// render function//加:level="1" 其中1代表数字1,如果不加冒号的话为字符串1const app = Vue.createApp({template: `<my-title :level="1">hello jessica</my-title>`});app.component('my-title',{props:['level'],render(){const {h}=Vue;// 虚拟 DOM// {//     tagName:'h2',//     text:'hello jessica',//     attributes:{}// }return h('h'+this.level,{},this.$slots.default());}})// app.component('my-title',{//     props:['level'],//     render(){//         const {h}=Vue;//         return h('h'+this.level,{name: 123123},'hello world');//     },//     template:`//         <h1 name="123123" v-if="level === 1"><slot /></h1>  //         <h2 v-if="level === 2"><slot /></h2>  //         <h3 v-if="level === 3"><slot /></h3>  //     `// })const vm = app.mount('#root');

解释:h(标签类型,属性对象,插槽) 它也可以嵌套

h('h'+this.level,{},[this.$slots.default(),h('h4',{},'huhu')])

插件Plugin

// plugin 插件 把通用功能封装起来const myPlugin={install(app,options){console.log(app,options);app.provide('name','Dell Lee');app.directive('focus',{mounted(el){el.focus();}});app.mixin({mounted(){console.log('mixin');}});app.config.globalProperties.$sayHello='hello world';}}const app = Vue.createApp({template: `<my-title />`});app.component('my-title',{inject:['name'],mounted(){console.log(this.$sayHello);},template:`<div>{{name}} <input v-focus/></div>`});app.use(myPlugin,{name:'jessica'})const vm = app.mount('#root');

mixin打印2次是因为2个组件一旦挂载成功就会执行(注意:先子组件后父组件 mixin里生命周期函数优先级高于组件里优先级(并不会覆盖,只是先后顺序问题)

对数据做校验的插件(有bug默认值没有校验)

const app = Vue.createApp({data() {return {name: 'dell',age: 28}},rules: {age: {validate: age => age > 25,message: 'too young,to simple'},name: {validate: name => name.length >= 4,message: 'name too short'}},template: `<div>name:{{name}},age:{{age}}</div>`});const validatePlugin = (app, options) => {app.mixin({created() {//console.log('mixin ready');//表示当组件初始化差不多结束的时候才执行for (let key in this.$options.rules) {const item = this.$options.rules[key];//获取key:age里面的值this.$watch(key, (value) => {const result = item.validate(value);if (!result) console.log(item.message);});}}})};app.use(validatePlugin);const vm = app.mount('#root');

默认值比如年龄23,没有进行校验,还没想出解决方案

CompositionAPI使用

setup(props,context)作用方式:在实例被完全初始化之前执行的函数

const app = Vue.createApp({template: `<div @click="handleClick">{{name}}</div>`,methods:{test(){console.log(this.$options.setup());}},mounted(){this.test();},// 实例被完全初始化之前执行的函数setup(props,context){return{name:'dell',handleClick:()=>{alert(123)}}}});const vm = app.mount('#root');

解释说明:在setup方法里无法调用外部的方法,模板和生命周期函数,而在外部这些实例的方法或生命周期函数能直接调用setup方法,原因是setup方法执行的时候这个实例并没有被创建并没有完成初始化压根不存在this 拿不到app实例,但是在app实例创建好之后呢 这个setup已经被挂载到app实例上,所以当你有这个实例时候,你在这个实例一定可以获取到setup方法

ref和reactive响应式的引用

原理:通过proxy对数据进行封装,当数据变化时,触发模板等内容的更新

ref处理基础类型的数据,如:字符串,数字(都封装成对象形式,自动调用对象.value显示)

reactive处理非基础类型的数据,如:数组,对象(都封装成原来的样子显示)

Vue在对模板处理的时候会进行转化,当他知道返回的name是一个响应式引用,底层会自动帮我们调用name.value,因此我们只需要写{{name}}就可以显示

const app = Vue.createApp({template: `<div>{{arr[0]}}</div>`,//<div>{{name}}</div> 基本类型写法//<div>{{nameObj.name}}</div> 对象类型写法// 实例被完全初始化之前执行的函数// setup(props, context) {//     const {ref}=Vue;//     // proxy,'dell' 变成 proxy({value:'dell'}) 这样的一个响应式引用//     let name = ref('dell');//     // 设置延时器//     setTimeout(() => {//         name.value = 'lee'//     }, 2000);//     return { name }// }// setup(props, context) {//     const {reactive}=Vue;//     // proxy,{name:'zhangsan'} 变成 proxy({name:'zhangsan'}) 这样的一个响应式引用//     let nameObj = reactive({name:'zhangsan'});//     // 设置延时器//     setTimeout(() => {//         nameObj.name='lisi'//     }, 2000);//     return { nameObj }// }setup(props, context) {const { reactive } = Vue;let arr = reactive([123]);// 设置延时器setTimeout(() => {arr[0] = 456}, 2000);return { arr }}});const vm = app.mount('#root');

2s后就变成lisi了

readonly只读不可修改会发生报警

const app = Vue.createApp({template: `<div>{{nameObj[0]}}</div>`,setup(props, context) {const { reactive,readonly } = Vue;let nameObj = reactive([123]);let copyNameObj=readonly(nameObj);// 设置延时器setTimeout(() => {nameObj[0] = 456,copyNameObj[0]=456}, 2000);return { nameObj,copyNameObj }}});const vm = app.mount('#root');

toRefs使用

const app = Vue.createApp({template: `<div>{{name}} {{age}}</div>`,setup(props, context) {const { reactive,readonly,toRefs } = Vue;let nameObj = reactive({name:'dell',age:28});// 设置延时器setTimeout(() => {nameObj.name='lee',nameObj.age=24}, 2000);// toRefs proxy({name:'dell',age:28}),//{// name:proxy({value:'dell'}),// age:proxy({value:24})    //}const {name,age}=toRefs(nameObj);return { name,age }}});const vm = app.mount('#root');

记住: 创建reactive对象直接解构的话不能在模板上直接使用的,它不具备响应式,想具备响应式必须调用toRefs做一个转化,再做解构,在模板上就可以响应显示了

toRef使用

如果一个对象上本来没有其属性,但是后面你又想给其添加属性,就可以使用toRef(不建议使用)

// toRef,contextconst app = Vue.createApp({template: `<div>{{age}}</div>`,setup(props, context) {const { reactive,toRef } = Vue;// 推荐注释起来的使用,下面只是为了演示// const data=reactive({name:'dell',age:''});const data=reactive({name:'dell'});const age=toRef(data,'age');setTimeout(()=>{age.value='28'},2000);return {age}}});const vm = app.mount('#root');

context使用

emit传统使用

const app = Vue.createApp({methods: {handleChange() {alert('change')}},template: `<child @change="handleChange">parent</child>`,});app.component('child', {mounted(){this.$emit('change');},setup(props,context){const {h}=Vue;const {attrs,slots,emit}=context;return ()=> h('div',{},slots.default());}})const vm = app.mount('#root');

结果:先弹出窗口,再显示parent

emit使用CompositionAPI

const app = Vue.createApp({methods: {handleChange() {alert('change')}},template: `<child @change="handleChange"></child>`,});app.component('child', {template:`<div @click="handleClick">123123</div>`,setup(props,context){const {attrs,slots,emit}=context;function handleClick(){emit('change');}return {handleClick};}})const vm = app.mount('#root');

结果:先显示123123,然后点击弹出窗口

attrs

const app = Vue.createApp({template: `<child app="app"></child>`,});app.component('child', {template:`<div>child</div>`,setup(props,context){const {attrs,slots,emit}=context;console.log(attrs.app);//appreturn {};}})const vm = app.mount('#root');

slots

const app = Vue.createApp({template: `<child>parent</child>`,});app.component('child', {mounted(){console.log(this.$slots);},setup(props,context){const {h}=Vue;const {attrs,slots,emit}=context;//console.log(slots);return ()=>h('div',{},slots.default());}})const vm = app.mount('#root');

实例输入添加到list显示

// 关于list 操作的内容进行了封装const listRelativeEffect = () => {const { reactive } = Vue;const list = reactive([]);const addItemToList = (item) => {list.push(item);}return {list,addItemToList}}// 关于 inputValue 操作的内容进行封装const inputRelativeEffect = () => {const { ref } = Vue;const inputValue = ref('');const handleInputValueChange = (e) => {inputValue.value = e.target.value;}return {inputValue,handleInputValueChange};}const app = Vue.createApp({setup() {const {list,addItemToList}=listRelativeEffect();const {inputValue,handleInputValueChange}=inputRelativeEffect();return{list,addItemToList,inputValue,handleInputValueChange}},template: `<div><div><input :value="inputValue" @input="handleInputValueChange"  /><button @click="addItemToList(inputValue)">提交</button>   </div><ul><li v-for="(item,index) in list" :key="index">{{item}}</li>    </ul>    </div>`});const vm = app.mount('#root');

computed属性

// computed计算属性const app = Vue.createApp({setup() {const {reactive,computed}=Vue;const countObj=reactive({count:0});const handleClick=()=>{countObj.count+=1;};let countAddFive=computed({get:()=>{return countObj.count+5;},set:(param)=>{countObj.count=param-5;}});setTimeout(()=>{countAddFive.value=100;},3000);return {countObj,countAddFive,handleClick};},template: `<div><span @click="handleClick">{{countObj.count}}</span> --{{countAddFive}}   </div>`});const vm = app.mount('#root');

watch监听

使用ref时,watch(对象,()=>{}),而使用reactive时,watch([()=>对象],([])=>{}) 注意:当只有一个对象数组可以去掉

// watch 监听const app = Vue.createApp({setup() {const {ref,watch} =Vue;const name=ref('dell');// 具备一定的惰性 lazy// 参数可以拿到原始和当前值// 可以侦听多个数据的变化,用一个侦听器承载watch(name,(currentValue,prevValue)=>{console.log(currentValue,prevValue);})return {name};},template: `<div><div>Name:<input v-model="name"/></div><div>Name is {{name}}</div></div>`});const vm = app.mount('#root');

// watch 监听const app = Vue.createApp({setup() {const {reactive,watch,toRefs} =Vue;const nameObj=reactive({name:'张三',englishName:'zhangsan'});// 具备一定的惰性 lazy// 参数可以拿到原始和当前值// 可以侦听多个数据的变化,用一个侦听器承载watch([()=>nameObj.name,()=>nameObj.englishName],([curName,curEng],[prevName,prevEng])=>{console.log('中文名:'+curName,prevName+',英文名:'+curEng,prevEng);});const {name,englishName}=toRefs(nameObj);return {name,englishName};},template: `<div><div>Name:<input v-model="name"/></div><div>Name is {{name}}</div><div>engName:<input v-model="englishName"/></div><div>engName is {{englishName}}</div></div> `});const vm = app.mount('#root');

 

watchEffect监听器

// watchEffect 监听const app = Vue.createApp({setup() {const {reactive,watchEffect,toRefs} =Vue;const nameObj=reactive({name:'张三',englishName:'zhangsan'});// 立即执行,没有惰性// 不需要传递你要侦听的内容,自动会感知代码依赖// 不需要传递很多参数,只需要一个回调函数// 不能获取之前数据的值const stop=watchEffect(()=>{console.log(nameObj.name);console.log(nameObj.englishName);setTimeout(()=>{stop();},5000);});const {name,englishName}=toRefs(nameObj);return {name,englishName};},template: `<div><div>Name:<input v-model="name"/></div><div>Name is {{name}}</div><div>engName:<input v-model="englishName"/></div><div>engName is {{englishName}}</div></div> `});const vm = app.mount('#root');

如果你监听的内容没依赖代码的变化,那么该监听器只会立即执行一次,而watch监听器本身是惰性,想要改变也可以,只需要增加第三个参数{immediate:true}

CompositionAPI生命周期函数

mounted(){}:// dom结构挂载完成之后打印出来

特别注意:CompositionAPI里面没有beforeCreate,created,因为setup()执行时间点在beforeCreate和created两者之间,但是,CompositionAPI却增加了onRenderTracked(页面渲染时,每次都会收集响应式依赖就会自动执行)onRenderTriggered(页面渲染时,每次都会收集响应式依赖第一次渲染不会打印)

const app = Vue.createApp({// 特别注意:CompositionAPI里面没有beforeCreate,created// beforeMount => onBeforeMount// mounted => onMountedsetup() {const {ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted,onRenderTracked,onRenderTriggered}=Vue;const name=ref('dell');onBeforeMount(()=>{console.log('onBeforeMount');});onMounted(()=>{console.log('onMounted');});onBeforeUpdate(()=>{console.log('onBeforeUpdate');});onUpdated(()=>{console.log('onUpdated');});onRenderTracked(()=>{console.log('onRenderTracked');});onRenderTriggered(()=>{console.log('onRenderTriggered');});const handleClick=()=>{name.value='lee';};return {name,handleClick};},template: `<div @click="handleClick">{{name}}</div> `});const vm = app.mount('#root');

单向数据流(子组件不能改变父组件传递过来的数据)

// 单向数据流const app = Vue.createApp({setup() {const {provide,ref,readonly}=Vue;const name=ref('dell')provide('name',readonly(name));provide('changeName',(value)=>{name.value=value;})return {};},template: `<div><child /></div> `});app.component('child',{setup(){const {inject}=Vue;// inject('name','hello') 给name默认值helloconst name=inject('name');const changeName=inject('changeName');const handleClick=()=>{// 因为父组件设置了readonly可以有效限制了 子组件进行数据变化// name.value='jessica';changeName('lee');};return {name,handleClick};},template:`<div @click="handleClick">{{name}}</div>`})const vm = app.mount('#root');

获取模板dom元素的节点

const app=Vue.createApp({setup(){const { ref,onMounted }=Vue;const hello=ref(null);onMounted(()=>{console.log(hello.value);})return {hello};},template:`<div ref="hello">hello world</div>`});const vm = app.mount('#root');

结论:CompositionAPI的语法下,获取真实的DOM元素节点

Vue基础入门(下)相关推荐

  1. Vue基础入门(二)

    Vue基础入门目录 一.过滤器vue3已经删除!!!!!! 1.什么是过滤器(Filters) 2.代码展示 3.私有过滤器和全局过滤器 4.过滤器的注意点 5.优化时间代码示例 二.watch 侦听 ...

  2. Qt学习之Qt基础入门(下)

    1. 前言 前两篇博客简单的阐述了一下Qt的入门用法,这篇博客继续跟着视频学习. Qt入门系列: Qt学习之C++基础 Qt学习之Qt安装 Qt学习之Qt基础入门(上) Qt学习之Qt基础入门(中) ...

  3. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十八║Vue基础: 指令(下)+计算属性

    回顾 今天来晚辣,给公司做了一个小项目,一个瀑布流+动态视频控制的DEMO,有需要的可以联系我,公司的项目就不对外展示了(一个后端程序员真的要干前端了哈哈哈). 书接上文,昨天正式的开始了Vue的代码 ...

  4. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十八║Vue基础: 指令(下)+计算属性+watch...

    回顾 今天来晚辣,给公司做了一个小项目,一个瀑布流+动态视频控制的DEMO,有需要的可以联系我,公司的项目就不对外展示了(一个后端程序员真的要干前端了哈哈哈). 书接上文,昨天正式的开始了Vue的代码 ...

  5. 第一章 Vue基础入门

    文章目录 引言 1.快速入门 1.1.创建项目 1.2.模型和视图 1.3.双向数据绑定 2.{{ }} - 插值 2.1.语法 2.2.案例 3.v-text.v-html(内容绑定) 3.1 语法 ...

  6. Vue(三):vue基础入门

    目录 一.侦听器 1.1 什么是watch侦听器 1.2 方法格式的侦听器的应用--判断用户名是否被占用 ​1.3 immediate属性-对象格式的侦听器 1.4 deep属性-对象格式的侦听器 二 ...

  7. Vue基础入门(2) Vue.js下载与安装

    下载与安装Vue.js Vue.js的官网: https://cn.vuejs.org/ 如果在项目中使用Vue.js框架,有两种方式:一是在页面中使用Script的方式直接引入,可以在官网下载Vue ...

  8. mysql 同一张表 某个字段更新到另一条数据上_面试基础:数据库MySQL基础入门(下)...

    本文是面试基础的第二篇.本篇偏理论,包括三节: 事务和并发 数据库设计 索引 所选的三个内容均是面试的高频考察点,需要细致地理解 No.1     事务和并发 事务:数据库操作的基本单元.对于数据库的 ...

  9. vue基础入门-应用 组件实例

    https://v3.cn.vuejs.org/guide/instance.html#%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%BA%94%E7%94%A8%E ...

最新文章

  1. 对《软件工程》第四章的理解
  2. Java程序员面试如何超常发挥?
  3. python基础教程 pdf github_python基础教程之Jupyter导出PDF从入门到绝望(已解|python基础教程|python入门|python教程...
  4. servelet基础
  5. 干掉耐克的,绝不会是下一个耐克?
  6. js调用浏览器的下载框
  7. python质数列_现代化程序开发笔记(3)——多文件与模块
  8. CentOS 7.6 下安装 MySQL8.0.13
  9. 创建外部快照_快照事件:现在如何仅通过拍照即可创建日历事件
  10. Angular之ngx-permissions的路由使用
  11. web开发时浏览器兼容性问题汇总
  12. 摄影测量与遥感资质乙级标准内容
  13. matlab正弦余弦与圆的关系
  14. 华为宣布人事调整:余承东调离华为云
  15. Epay纵横支付 游戏账号点券全通道支付系统 | 抖音虎牙快手yy直播QB支付,DNF游戏点券,全通道几十种支持,亲测
  16. php 函数索引 中文索引
  17. 无序数组中获取第k个最大数
  18. JDK14打包工具jpackage的使用
  19. 对ArrayList集合里面数据排序
  20. 美国亚马逊卖家注册美国商标需要多少时间和费用?

热门文章

  1. 【QML】MouseArea
  2. Python中json自定义jsonschema进行json数据格式校验
  3. 使用django实现某淘客网站采集功能
  4. AcWing1102. 移动骑士
  5. Halcon--差异模型完整性检测
  6. 4K H.265和H.264
  7. 树莓派python工业数据采集系统
  8. IPC连接错误号分析
  9. 为什么我们依然觉得AI换脸很“假”?
  10. 企业舆情风险管控方案