vue基础

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta http-equiv="X-UA-Compatible" content="ie=edge">

<title>Document</title>

</head>

<script src="./vue.js"></script>

<body>

<!-- v-bind动态传递prop -->

<!-- v-bind 动态赋值 -->

<div id="blog-post-demo">

<blog-post

v-for="post in posts"

v-bind:key="post.id"

v-bind:title="post.title"

v-bind:content="post.content"

></blog-post>

<!-- 重构blog-post让它变成接受一个单独的 post prop -->

<!--通过 v-on 监听子组件实例的任意事件-->

<div :style="{ fontSize: postFontSize1 + 'em' }">

<blog-posts

v-on:enlarge-texts="postFontSize1 += 0.1"

v-for="post in posts"

v-bind:key="post.id"

v-bind:post="post"

></blog-posts>

</div>

<!-- <blog-pos> 组件决定它的文本要放大多少 -->

<div :style="{ fontSize: postFontSize2 + 'em' }">

<blog-pos

v-on:enlarge-tex="postFontSize2 += $event"

v-for="post in posts"

v-bind:key="post.id"

v-bind:post="post"

></blog-pos>

</div>

<!-- fontsize写在一个方法里 -->

<div :style="{ fontSize: postFontSize + 'em' }">

<blog-po

v-on:enlarge-text="onEnlargeText"

v-for="post in posts"

v-bind:key="post.id"

v-bind:post="post"

></blog-po>

</div>

<div>

<input v-model="searchText">

<span>{{searchText}}</span>

<!-- 上面等价于下面 -->

<input

v-bind:value="searchText2"

v-on:input="searchText2 = $event.target.value"

><span>{{searchText2}}</span>

</div>

<!-- 组件上v-modle -->

<custom-input

v-bind:value="searchTex"

v-on:input="searchTex = $event"

></custom-input>

<span>{{searchTex}}</span>

<custom-input v-model="searchTex"></custom-input>

</div>

<!-- 插槽 -->

<div>

<alert-box>

Something bad happened.

</alert-box>

</div>

<!-- <div id="#transition-components-demo">

<transition name="component-fade" mode="out-in">

<component v-bind:is="view"></component>

</transition>

</div> -->

</body>

<script>

// new Vue({

// el: '#transition-components-demo',

// data: {

// view: 'v-a'

// },

// components: {

// 'v-a': {

// template: '<div>Component A</div>'

// },

// 'v-b': {

// template: '<div>Component B</div>'

// }

// }

// })

Vue.component('blog-post', {

props: ['title','content'],//多个属性就有点复杂了,下面(blog-posts)进行了优化

template: `<div class="blog-post"><h3>{{ title }}</h3><div v-html="content">{{content}}</div></div>`

//每个组件必须只有一个根元素

})

Vue.component('blog-posts', {//调用内建的 $emit 方法 并传入事件名称来触发一个事件(事件名称在父组件中)

props: ['post'],

template: `

<div class="blog-post">

<h3>{{ post.title }}</h3>

<button v-on:click="$emit('enlarge-texts')">enlarge-texts</button>

<div v-html="post.content"></div>

</div>

`

})

Vue.component('blog-pos', {//使用事件抛出一个值

props: ['post'],

template: `

<div class="blog-post">

<h3>{{ post.title }}</h3>

<button v-on:click="$emit('enlarge-tex', 0.1)">使用事件抛出一个值</button>

<div v-html="post.content"></div>

</div>

`

})

Vue.component('blog-po', {//事件是一个方法

props: ['post'],

template: `

<div class="blog-post">

<button v-on:click="$emit('enlarge-text',0.1)">方法</button>

<div v-html="post.content"></div>

</div>

`

})

// v-modle组件上

Vue.component('custom-input', {

props: ['value'],

template: `

<input

v-bind:value="value"

v-on:input="$emit('input', $event.target.value)"

>

`

})

// 插槽

Vue.component('alert-box', {

template: `

<div class="demo-alert-box">

<strong>Error!</strong>

<slot></slot>

</div>

`

})

//动态组件???? <component v-bind:is="currentTabComponent"></component><!-- 组件会在 `currentTabComponent` 改变时改变 -->

//组件规范:

//组件名称:推荐-字母全小写且必须包含一个连字符;

// 两种命名方式-使用 kebab-case,引用这个自定义元素时使用 kebab-case ;使用 PascalCase,引用这个自定义元素时两种命名法都可以使用

// 用入口文件 (比如 src/main.js) 中全局导入基础组件的示例代码:

// import Vue from 'vue'

// import upperFirst from 'lodash/upperFirst'

// import camelCase from 'lodash/camelCase'

 

// const requireComponent = require.context(

// // 其组件目录的相对路径

// './components',

// // 是否查询其子目录

// false,

// // 匹配基础组件文件名的正则表达式

// /Base[A-Z]\w+\.(vue|js)$/

// )

 

// requireComponent.keys().forEach(fileName => {

// // 获取组件配置

// const componentConfig = requireComponent(fileName)

 

// // 获取组件的 PascalCase 命名

// const componentName = upperFirst(

// camelCase(

// // 剥去文件名开头的 `./` 和结尾的扩展名

// fileName.replace(/^\.\/(.*)\.\w+$/, '$1')

// )

// )

 

// 全局注册组件

// Vue.component(

// componentName,

// // 如果这个组件选项是通过 `export default` 导出的,

// // 那么就会优先使用 `.default`,

// // 否则回退到使用模块的根。

// componentConfig.default || componentConfig

// )

// })

// prop

// camelCase的 prop 名需要使用其等价的 kebab-case命名:props: ['postTitle']----<blog-post post-title="hello!"></blog-post>

// 传入一个对象 两种方式

// 1.<blog-post

// v-bind:author="{

// name: 'Veronica',

// company: 'Veridian Dynamics'

// }"

// ></blog-post>

// 2.<blog-post v-bind:author="post.author"></blog-post>用一个变量进行动态赋值

//传入一个对象所有属性

//<blog-post v-bind="post"></blog-post>等价于<blog-post v-bind:id="post.id" v-bind:title="post.title"></blog-post>

// prop验证:

// 那些 prop 会在一个组件实例创建之前进行验证,所以实例的属性 (如 data、computed 等) 在 default 或 validator 函数中是不可用的。

// 非 Prop 的特性:

/*替换/合并已有的特性:对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。庆幸的是,class 和 style 特性会稍微智能一些,即两边的值会被合并起来

禁用特性继承:如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs: false,但不会影响 style 和 class 的绑定。

ps:$attrs 属性包含了传递给一个组件的特性名和特性值

*/

//自定义事件

/*

1.推荐使用 kebab-case 的事件名。

2.在一个组件的根元素上直接监听一个原生事件:使用 v-on 的 .native 修饰符,v-on:focus.native="onFocus"

3.Vue 提供了一个 $listeners 属性,它是一个对象,里面包含了作用在这个组件上的所有监听器(可解决native失效问题)

4.带有 .sync 修饰符的 v-bind 不能和表达式一起使用

// 插槽

1.如果 <navigation-link> 没有包含一个 <slot> 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃

2.编译作用域:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

3.在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称,

v-slot 只能添加在一个 <template> 上

4.默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确;

只要出现多个插槽,请始终为所有的插槽使用完整的基于 <template> 的语法

5.v-slot缩写#,该缩写只在其有参数的时候才可用,eg: #="{ user }"无效, #default="{ user }"

// 动态组件、异步组件

1.多标签的界面中使用 is 特性来切换不同的组件

2.标签的组件实例要第一次被创建的时候缓存下来,可以用一个 <keep-alive> 元素将其动态组件包裹起来;

<keep-alive> 要求被切换到的组件都有自己的名字,不论是通过组件的 name 选项还是局部/全局注册。

// 处理边界情况

1.在每个 new Vue 实例的子组件中,其根实例可以通过 $root 属性进行访问(小型项目中少量组件可以),一般情况下用Vuex

2.和 $root 类似,$parent 属性可以用来从一个子组件访问父组件的实例

3.$refs 只会在组件渲染完成之后生效,避免在模板或计算属性中访问 $refs

4.provide 选项允许我们指定我们想要提供给后代组件的数据/方法;使用 inject 选项来接收指定的我们想要添加在这个实例上的属性;

如果你想在祖先组件中更新所提供的数据,那么这意味着你可能需要换用一个像 Vuex 这样真正的状态管理方案了

5.$emit、$on, 和 $off 并不是 dispatchEvent、addEventListener 和 removeEventListener 的别名。

6.inline-template 会让模板的作用域变得更加难以理解。所以作为最佳实践,请在组件内优先选择 template 选项或 .vue 文件里的一个 <template> 元素来定义模板

7.一个组件包含了大量静态内容,可以在根元素上添加 v-once 特性以确保这些内容只计算一次然后缓存起来(不要过度使用这个模式)

// 进入/离开 & 列表渲染

1.

*/

new Vue({

el:'#blog-post-demo',

data:{

posts:[

{id:1,title:'My journey with Vue1',content:'<span>js</span>'},

{id:2,title:'My journey with Vue2',content:'<span>js</span>'},

{id:31,title:'My journey with Vue3',content:'<span>js</span>'}

],

postFontSize: 1,

postFontSize1: 1,

postFontSize2: 1,

searchText:'',

searchText2:'',

searchTex:''

},

methods: {

onEnlargeText: function (enlargeAmount) {//这个值将会作为第一个参数传入这个方法:

this.postFontSize += enlargeAmount

}

}

})

/*

可复用性&组合

混入:1.基础-当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

2.选项合并-数据对象在内部会进行递归合并,在和组件的数据发生冲突时以组件数据优先。

同名钩子函数(created)将混合为一个数组,因此都将被调用。

值为对象的选项,例如 methods, components 和 directives,将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对。

3.全局混入-谨慎使用全局混入对象,因为会影响到每个单独创建的 Vue 实例

4.自定义选项合并策略:如果想让自定义选项以自定义逻辑合并,可以向 Vue.config.optionMergeStrategies 添加一个函数,对于大多数对象选项,可以使用 methods 的合并策略。

自定义指令

钩子函数参数:除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

*/

</script>

</html>

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值