电子商务网站建设的开发方案哪些网站推广不收费
文章目录
- 模块与组件、模块化与组件化
- 模块
- 组件
- 模块化
- 组件化
- Vue中的组件含义
- 非单文件组件
- 基本使用
- 组件注意事项
- 使用 kebab-case
- 使用 PascalCase
- 组件的嵌套
- 模板template
- VueComponent
- 一个重要的内置功能
- 单文件组件
- Vue脚手架
- 使用Vue CLI脚手架
- 先配置环境
- 初始化脚手架
- 分析脚手架结构
- 实例
- render函数——解决无模板解析
- 修改默认配置
- ref属性——定位元素
- props配置项——传递参数
- :age="20"和 age="20的区别"
- mixin混入
- plugin插件
- scoped样式
- 插槽Slot
- 实例
- 自定义事件
模块与组件、模块化与组件化
模块
- 理解:向外提供特定功能的 js 程序,一般就是一个 js 文件
- 为什么:js 文件很多很复杂
- 作用:复用 js,简化 js 的编写,提高 js 运行效率
组件
- 定义:用来实现局部功能的代码和资源的集合(html/css/js/image…)
- 为什么:一个界面的功能很复杂
- 作用:复用编码,简化项目编码,提高运行效率
模块化
当应用中的 js 都以模块来编写的,那这个应用就是一个模块化的应用
组件化
当应用中的功能都是多组件的方式来编写的,那这个应用就是一个组件化的应用
Vue中的组件含义
组件是可复用的Vue实例
, 说白了就是一组可以重复使用的模板
, 跟JSTL的自定义标签、Thymeleal的th:fragment
等框架有着异曲同工之妙,通常一个应用会以一棵嵌套的组件树的形式来组织:
- 组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树
在这里插入图片描述
例如,你可能会有页头
、侧边栏
、内容区
等组件,每个组件又包含了其它的像导航链接
、博文之类的组件。
非单文件组件
基本使用
<!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"><script type="text/javascript" src="../js/vue.js"></script><title>Document</title>
</head>
<body><div id="root"><!-- 3使用组件 --><school></school><student></student></div><script type="text/javascript">//1创建组件const school=Vue.extend({template: `<div><h1>{{schoolName}}</h1><h2>{{address}}</h2></div>`,data() {return {schoolName: '一中',address: '柳岸'}},})//1创建组件的快捷方式const student={template: `<div><h1>{{studentName}}</h1><h2>{{age}}</h2></div>`,data() {return {studentName: 'lsc',age: 22}},}//2全局注册组件Vue.component('student',student)new Vue({el: '#root',data: {msg: 'hello compentments'},//2局部注册组件components: {school:school //这种可以简写为 school}})</script>
</body>
</html>
总结:
Vue中使用组件的三大步骤:
-
定义组件(创建组件)——Vue.extend
-
注册组件——局部和全局
-
使用组件(写组件标签)
如何定义一个组件?
-
使用
Vue.extend(options)创建
,其中options和new Vue(options)时传入的options几乎一样,但也有点区别: -
el不要写,为什么?
- 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器
-
data必须写成函数,为什么?
- 避免组件被复用时,数据存在引用关系,防止同一个组件的实例对象之间数据相互影响
如何注册组件?
- 局部注册:new Vue的时候传入components选项
- 全局注册:Vue.component(‘组件名’,组件)
全局注册
Vue.component('my-component-name', { // ... 选项 ... })
这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的 Vue 根实例 (
new Vue
) 的模板中Vue.component('component-a', { /* ... */ }) Vue.component('component-b', { /* ... */ }) Vue.component('component-c', { /* ... */ })new Vue({ el: '#app' }) <div id="app"> <component-a></component-a> <component-b></component-b> <component-c></component-c> </div>
在所有子组件中也是如此,也就是说这三个组件
在各自内部也都可以相互使用。
局部注册
- 全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
在这些情况下,你可以通过一个普通的 JavaScript 对象来定义组件:
var ComponentA = { /* ... */ } var ComponentB = { /* ... */ } var ComponentC = { /* ... */ }
然后在
components
选项中定义你想要使用的组件:new Vue({el: '#app',components: {'component-a': ComponentA,'component-b': ComponentB} })
对于
components
对象中的每个 property 来说,其 property 名就是自定义元素的名字,其 property 值就是这个组件的选项对象。注意局部注册的组件在其子组件中不可用。例如,如果你希望
ComponentA
在ComponentB
中可用,则你需要这样写:var ComponentA = { /* ... */ }var ComponentB = {components: {'component-a': ComponentA},// ... }
如果你通过 Babel 和 webpack 使用 ES2015 模块
import ComponentA from './ComponentA.vue'export default {components: {ComponentA},// ... }
注意在 ES2015+ 中,在对象中放一个类似
ComponentA
的变量名其实是ComponentA: ComponentA
的缩写,即这个变量名同时是用在模板中的自定义元素的名称
- 包含了这个组件选项的变量名
如何使用
编写组件标签:<school></school>
组件注意事项
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>组件注意事项</title><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><h1>{{msg}}</h1><school></school></div></body><script type="text/javascript">Vue.config.productionTip = falseconst school = Vue.extend({name:'atguigu',template:`<div><h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div>`,data(){return {name:'尚硅谷',address:'北京'}}})new Vue({el:'#root',data:{msg:'欢迎学习Vue!'},components:{school}})</script>
</html>
总结:
关于组件名:
一个单词组成:
-
第一种写法(首字母小写):school
-
第二种写法(首字母大写):School
多个单词组成:
-
第一种写法(kebab-case命名):my-school
-
第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
组件名大小写
定义组件名的方式有两种:
使用 kebab-case
Vue.component('my-component-name', { /* ... */ })
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如
<my-component-name>
。使用 PascalCase
Vue.component('MyComponentName', { /* ... */ })
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说
<my-component-name>
和<MyComponentName>
都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
备注:
-
组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行
-
可以使用name配置项指定组件在开发者工具中呈现的名字
关于组件标签:
-
第一种写法:
<school></school>
-
第二种写法:
<school/>
-
备注:不使用脚手架时,
<school/>
会导致后续组件不能渲染
一个简写方式:const school = Vue.extend({options})可简写为:const school = {options}
组件的嵌套
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>组件的嵌套</title><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"></div></body><script type="text/javascript">Vue.config.productionTip = false//定义student组件const student = Vue.extend({template:`<div><h2>学生名称:{{name}}</h2> <h2>学生年龄:{{age}}</h2> </div>`,data(){return {name:'JOJO',age:20}}})//定义school组件const school = Vue.extend({template:`<div><h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> <student></student></div>`,components:{student},data(){return {name:'尚硅谷',address:'北京'}}})//定义hello组件const hello = Vue.extend({template:`<h1>{{msg}}</h1>`,data(){return {msg:"欢迎学习尚硅谷Vue教程!"}}})//定义app组件const app = Vue.extend({template:`<div><hello></hello><school></school></div>`,components:{school,hello}})//创建vmnew Vue({template:`<app></app>`,el:'#root',components:{app}})</script>
</html>
效果:
- 对于一个组件想嵌套在哪个组件中,就要将对于的字组件嵌套在对应的父组件中
模板template
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script language="JavaScript" src="static/script/vue.js"></script>
</head>
<body>
<!--view层 模板-->
<div id="app"><myfirstcomponent></myfirstcomponent>
</div><script language="JavaScript">// 定义一个Vue组件Vue.component("myfirstcomponent", {template: '<div> hello,我是一个组件 </div>'});var vm=new Vue({el: "#app",data: {}});
</script>
</body>
</html>
- 组件的第一个参数就是组件名
- 当直接在 DOM 中使用一个组件 (而不是在字符串模板或单文件组件) 的时候,我们强烈推荐遵循 W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符)。这会帮助你避免和当前以及未来的 HTML 元素相冲突。
- 组件失效的原因
- 没有实例化某个Vue对象
- 组件必须挂载在某个Vue实例之下,否则不会生效
- 标签名称不能有大写字母
- 创建组件构造器和注册组件的代码必须在Vue实例之前
VueComponent
const school = Vue.extend({name:'atguigu',template:`<div><h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> </div>`,data(){return {name:'尚硅谷',address:'北京'}}})
关于VueComponent:
-
school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
-
我们只需要写
<school/>或<school></school>
,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options) -
特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!
-
关于this指向:
-
组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是VueComponent实例对象
-
new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是Vue实例对象
-
VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)
-
Vue的实例对象,以后简称vm
-
只有在本笔记中VueComponent的实例对象才简称为vc
- vc在创建的时候不能写el,只能跟着对应的vm的时候,来决定
一个重要的内置功能
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>一个重要的内置关系</title><script type="text/javascript" src="../js/vue.js"></script></head><body><div id="root"><school></school></div></body><script type="text/javascript">Vue.config.productionTip = falseVue.prototype.x = 99const school = Vue.extend({name:'school',template:`<div><h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> <button @click="showX">点我输出x</button></div>`,data(){return {name:'尚硅谷',address:'北京'}},methods: {showX(){console.log(this.x)}},})const vm = new Vue({el:'#root',data:{msg:'你好'},components:{school}})</script>
</html>
-
一个重要的内置关系:
VueComponent.prototype.__proto__ === Vue.prototype
- VueComponent.prototype指的是我们的VueComponent的原型对象 Vue.prototype指的是Vue的原型对象
-
为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue 原型上的属性、方法
- 通过显示原型链可以给原型对象添加属性,实例对象通过隐式原型链获取原型对象的属性,从自身沿着原型链一直找到window的原型对象为空
单文件组件
School.vue
<template><div id='Demo'><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><button @click="showName">点我提示学校名</button></div>
</template><script>export default {name:'School',data() {return {name:'尚硅谷',address:'北京'}},methods: {showName(){alert(this.name)}},}
</script><style>#Demo{background: orange;}
</style>
- export default 默认暴露,将我们的组件School暴露出去
- 可以使用name配置项指定组件在开发者工具中呈现的名字
- 其实export default {}是 简写 全称是 export default Vue.expend({optitons})
Student.vue
<template><div><h2>学生姓名:{{name}}</h2><h2>学生年龄:{{age}}</h2></div>
</template><script>export default {name:'Student',data() {return {name:'JOJO',age:20}},}
</script>
App.vue
<template><div><School></School><Student></Student></div>
</template><script>import School from './School.vue'import Student from './Student.vue'export default {name:'App',components:{School,Student}}
</script>
main.js
import App from './App.vue'new Vue({template:`<App></App>`,el:'#root',components:{App}
})
index.html
<!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>单文件组件练习</title>
</head>
<body><div id="root"></div><script src="../../js/vue.js"></script><script src="./main.js"></script>
</body>
</html>
- 直接这样写,并不能成功。需要我们的Vue 脚手架的帮助,才能实现
Vue脚手架
使用Vue CLI脚手架
先配置环境
Node.js
:http://nodejs.cn/download/安装就是无脑的下一步就好,安装在自己的环境目录下
- 确认nodejs安装成功
- cmd下输入node -v,查看是否能够正确打印出版本号即可!
- cmd下输入npm -v,查看是否能够正确打印出版本号即可!
- 这个npm,就是一个软件包管理工具,就和linux下的apt软件安装差不多!
Git
:https://git-scm.com/doenloads
初始化脚手架
- Vue 脚手架是 Vue 官方提供的标准化开发工具(开发平台)
- 最新的版本是 4.x
- 文档:Vue CLI
具体步骤
- 如果下载缓慢请配置 npm 淘宝镜像:npm config set registry http://registry.npm.taobao.org
-g 就是全局安装
npm install cnpm -g
或使用如下语句解决npm速度慢的问题
npm install --registry=https://registry.npm.taobao.org
- 但是能不用cnpm就不用,npm比较好,因为cnpm可能打包的时候会出现问题
- 全局安装@vue/cli——npm install -g @vue/cli
- 切换到你要创建项目的目录,然后使用命令创建项目:vue create xxx(项目名)
- 选择使用vue的版本,我们学习的是Vue2,所以选择2
- 启动项目:npm run serve
- 暂停项目:Ctrl+C
- Vue 脚手架隐藏了所有 webpack 相关的配置,若想查看具体的 webpakc 配置,请执行:vue inspect > output.js
呈现效果——访问http://localhost:8080/
- 这就是 Node.js的服务,跟tomcat 差不多。
- Node.js它是一个服务器,它可以运行一些东西。
分析脚手架结构
初始脚手架文件结构:
.文件目录
├── node_modules
├── public
│ ├── favicon.ico: 页签图标
│ └── index.html: 主页面
├── src
│ ├── assets: 存放静态资源
│ │ └── logo.png
│ │── component: 存放组件
│ │ └── HelloWorld.vue
│ │── App.vue: 汇总所有组件
│ └── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件
├── README.md: 应用描述文件
└── package-lock.json: 包版本控制文件
- main.js是一切的开端
实例
src/components/School.vue
<template><div id='Demo'><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><button @click="showName">点我提示学校名</button></div>
</template><script>export default {name:'School',data() {return {name:'尚硅谷',address:'北京'}},methods: {showName() {alert(this.name)}},}
</script><style>#Demo{background: orange;}
</style>
src/components/Student.vue
<template><div><h2>学生姓名:{{name}}</h2><h2>学生年龄:{{age}}</h2></div>
</template><script>export default {name:'Student',data() {return {name:'JOJO',age:20}},}
</script>
src/App.vue
<template><div><School></School><Student></Student></div>
</template><script>import School from './components/School.vue'import Student from './components/Student.vue'export default {name:'App',components:{School,Student}}
</script>
src/main.js
import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = falsenew Vue({//将App组件放入容器中render: h => h(App),
}).$mount('#app')
- 我们发现在main.js中,我们没有注册App组件,这些其实都是在render函数中,等会解释
public/index.html
<!DOCTYPE html>
<html lang=""><head><meta charset="UTF-8"><!-- 针对IE浏览器的特殊配置,含义是让IE浏览器以最高渲染级别渲染页面 --><meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- 开启移动端的理想端口 --><meta name="viewport" content="width=device-width, initial-scale=1.0"><!-- 配置页签图标 --><link rel="icon" href="<%= BASE_URL %>favicon.ico"><!-- 配置网页标题 --><title><%= htmlWebpackPlugin.options.title %></title></head><body><!-- 容器 --><div id="app"></div></body>
</html>
- 虽然在表面上我们没有使用
<script src="./main.js"></script>
来引入,但是我们可以进行使用<div id="app"></div>
,是因为脚手架帮我们做好了
render函数——解决无模板解析
import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = falsenew Vue({el:'#app',// 简写形式render: h => h(App),// 完整形式// render(createElement){// return createElement(App)// }// 因为只有一个参数所以可以把括号去掉 和一条语句只是return,写成render createElement =>return createElement(App)
})
总结:
关于不同版本的函数:
-
vue.js 与 vue.runtime.xxx.js的区别:
- vue.js 是完整版的 Vue,包含:核心功能+模板解析器
- vue.runtime.xxx.js 是运行版的 Vue,只包含核心功能,没有模板解析器,我们的import Vue from 'vue’引入的就是import Vue from ‘vue’
-
因为 vue.runtime.xxx.js 没有模板解析器,所以不能使用 template 配置项,需要使用 render函数接收到的createElement 函数去指定具体内容
修改默认配置
- vue.config.js 是一个可选的配置文件,如果项目的(和 package.json 同级的)根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载
- 使用 vue.config.js 可以对脚手架进行个性化定制,详见配置参考 | Vue CLI
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,lintOnSave:false /*关闭语法检查*/
})
webpack将配置文件放在了webpack.config.js中,这个文件被隐藏,就是防止我们乱改,对于我们想改Vue的配置,我们可以通过新建一个vue.config.js 文件,将这个文件和我们webpack.config.js进行合并,达到我们修改配置的功能
ref属性——定位元素
<template><div><h1 ref="title">{{msg}}</h1><Student ref="sch"/><button @click="show" ref="btn">点我输出ref</button></div>
</template><script>
import Student from '../components/Student.vue'export default {name:'App',components: { Student },data() {return {msg:'欢迎学习Vue!'}},methods:{show(){console.log(this.$refs.title)console.log(this.$refs.sch)console.log(this.$refs.btn)}}}
</script>
总结:
ref属性:
-
被用来给元素或子组件注册引用信息(id的替代者)
- 应用在html标签上获取的是真实DOM元素,应用在组件标签上获取的是组件实例对象(vc)
-
使用方式:
- 打标识:
<h1 ref="xxx"></h1> 或 <School ref="xxx"></School>
- 打标识:
-
获取:this.$refs.xxx
props配置项——传递参数
像上面那样用组件没有任何意义,所以我们是需要传递参数到组件
的,此时就需要使用props
属性了!注意:默认规则下props属性里的值不能为大写
;
HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名:
src/App.vue
<template><div><h1>{{msg}}</h1><Student name="JOJO" sex="男" :age="20" /><Student name="POKO" sex="男" :age="30" /><Student name="SJO" sex="女" :age="25" /></div>
</template><script>import Student from './components/Student'export default {name:'App',components:{Student},data() {return {msg: '我是一个正常人'}},}
</script>
src/components/Student.vue
<template><div><h2>学生姓名:{{name}}</h2><h2>学生性别:{{sex}}</h2><h2>学生年龄:{{myage}}</h2><hr></div>
</template><script>export default {name:'Student',//简单接收// props:['name','age','sex'],// 接收的同时对数据进行类型限制// props:{// name:String,// age:Number,// sex:String// },// 接收的同时对数据进行类型限制 + 指定默认值 + 限制必要性props:{name:{type:String,required:true,},age:{type:Number,default:99},sex:{type:String,required:true}},data() {return {myage: this.age}},}
</script>
总结:
props配置项:
-
功能:让组件接收外部传过来的数据
-
传递数据:
<Demo name="xxx"/>
,在使用组件标签的时候,进行传递数据 -
接收数据:
- 第一种方式(只接收):props:[‘name’]
- 第二种方式(限制数据类型):props:{name:String}
- 第三种方式(限制类型、限制必要性、指定默认值):
props:{name:{type:String, //类型required:true, //必要性default:'JOJO' //默认值}
}
props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据
- 经过测试,我们发现对于组件来说,prop的属性的优先级是大于我们的data里面的属性,所以我们复制可以data() return{ mydata: this.prop}
:age="20"和 age=“20的区别”
- :age=“20” 的全称是v-bind:age=“20” ,也就是数据单向绑定了,而且我们知道这样绑定,""中的内容是表示js运算结果,所以传给age的值是数字20
- age=“20”,就表示传给age的值是一个字符串
mixin混入
src/mixin.js
//注册组件并暴露出去
export const mixin = {methods: {showName() {alert(this.name)}},mounted() {console.log("你好呀~")}
}
- 独立写一个混入的js文件
src/components/School.vue
<template><div><h2 @click="showName">学校姓名:{{name}}</h2><h2>学校地址:{{address}}</h2> </div>
</template><script>//局部引入混入import {mixin} from '../mixin'export default {name:'School',data() {return {name:'尚硅谷',address:'北京'}},//局部注册mixins:[mixin]}
</script>
src/components/Student.vue
<template><div><h2 @click="showName">学生姓名:{{name}}</h2><h2>学生性别:{{sex}}</h2> </div>
</template><script>// 局部引入混入import {mixin} from '../mixin'export default {name:'Student',data() {return {name:'JOJO',sex:'男'}},//局部注册mixins:[mixin]}
</script>
src/App.vue
<template><div><School/><hr/><Student/></div>
</template><script>import Student from './components/Student.vue'import School from './components/School.vue'export default {name:'App',components: { Student,School },}
</script>
全局混入:
src/main.js:
import Vue from 'vue'
import App from './App.vue'
import {mixin} from './mixin'Vue.config.productionTip = false
Vue.mixin(mixin)new Vue({el:"#app",render: h => h(App)
})
总结:
mixin(混入):
- 功能:可以把多个组件共用的配置提取成一个混入对象
使用方式:
第一步定义混入:
const mixin = {data(){....},methods:{....}....
}
第二步使用混入:
- 全局混入:Vue.mixin(xxx)
- 局部混入:mixins:[‘xxx’]
备注:
组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”,在发生冲突时以组件优先。
var mixin = {data: function () {return {message: 'hello',foo: 'abc'}}
}new Vue({mixins: [mixin],data () {return {message: 'goodbye',bar: 'def'}},created () {console.log(this.$data)// => { message: "goodbye", foo: "abc", bar: "def" }}
})
同名生命周期钩子将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
var mixin = {created () {console.log('混入对象的钩子被调用')}
}new Vue({mixins: [mixin],created () {console.log('组件钩子被调用')}
})// => "混入对象的钩子被调用"
// => "组件钩子被调用"
plugin插件
src/plugin.js:
export default {install(Vue,x,y,z){console.log(x,y,z)//全局过滤器Vue.filter('mySlice',function(value){return value.slice(0,4)})//定义混入Vue.mixin({data() {return {x:100,y:200}},})//给Vue原型上添加一个方法(vm和vc就都能用了)Vue.prototype.hello = ()=>{alert('你好啊')}}
}
- 独立写一个插件的js文件
src/main.js:
import Vue from 'vue'
import App from './App.vue'
import plugin from './plugin'Vue.config.productionTip = false
Vue.use(plugin,1,2,3)new Vue({el:"#app",render: h => h(App)
})
src/components/School.vue:
<template><div><h2>学校姓名:{{name | mySlice}}</h2><h2>学校地址:{{address}}</h2> </div>
</template>
<script>export default {name:'School',data() {return {name:'尚硅谷atguigu',address:'北京'}}}
</script>
src/components/Student.vue:
<template><div><h2>学生姓名:{{name}}</h2><h2>学生性别:{{sex}}</h2> <button @click="test">点我测试hello方法</button> </div>
</template>
<script>export default {name:'Student',data() {return {name:'JOJO',sex:'男'}},methods:{test() {this.hello()}}}
</script>
总结:
插件:
- 功能:用于增强Vue
- 本质:
包含install方法的一个对象
,install的第一个参数是Vue,也就vm实例对象的构造函数,第二个以后的参数是插件使用者传递的数据
定义插件:
plugin.install = function (Vue, options) {// 1.添加全局过滤器Vue.filter(....)// 2.添加全局指令Vue.directive(....)// 3. 配置全局混入Vue.mixin(....)// 4. 添加实例方法Vue.prototype.$myMethod = function () {...}Vue.prototype.$myProperty = xxxx
}
使用插件:Vue.use(plugin)
scoped样式
src/components/School.vue
<template><div class="demo"><h2>学校姓名:{{name}}</h2><h2>学校地址:{{address}}</h2> </div>
</template><script>export default {name:'School',data() {return {name:'尚硅谷',address:'北京'}}}
</script><style scoped>.demo{background-color: blueviolet;}
</style>
src/components/Student.vue
<template><div class="demo"><h2>学生姓名:{{name}}</h2><h2>学生性别:{{sex}}</h2> </div>
</template><script>export default {name:'Student',data() {return {name:'JOJO',sex:'男'}}}
</script><style scoped>.demo{background-color: chartreuse;}
</style>
src/App.vue
<template><div><School/><Student/></div>
</template><script>import Student from './components/Student.vue'import School from './components/School.vue'export default {name:'App',components: { Student,School },}
</script>
总结:
scoped
样式:
- 作用:让样式在局部生效,防止冲突
- 我们在给组件写对应的样式时,可能会有类名相同而导致样式冲突,所以对于组件的样式,我们最好能让其只在组件内局部生效,而不影响其他组件的样式
- 写法:
<style scoped>
scoped
样式一般不会在App.vue
中使用
插槽Slot
实例
定义插槽模板
Vue.component('todo',{template:'<div>\<slot name="todo-title"></slot>\<ul>\<slot name="todo-items"></slot>\</ul>\</div>'});
创建对应的组件
Vue.component('todo-title',{props:['title'],template:'<div>{{title}}</div>'});Vue.component("todo-items",{props:["item"],template:"<li>{{item}}</li>"});
实例Vue并初始化数据
var vm = new Vue({el:"#app",data:{title:"博客",todoItems:['Java','Php','C#']}});
将这些值,通过插槽插入
<div id="app"><todo><todo-title slot="todo-title" :title="title"></todo-title><todo-items slot="todo-items" v-for="item in todoItems" :item="item"></todo-items></todo>
</div>
完整代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<!--view层,模板-->
<div id="app"><todo><todo-title slot="todo-title" :title="title"></todo-title><todo-items slot="todo-items" v-for="item in todoItems" :item="item"></todo-items></todo>
</div>
<script language="JavaScript" src="static/script/vue.js"></script>
<script type="text/javascript">Vue.component('todo-title',{props:['title'],template:'<div>{{title}}</div>'});Vue.component("todo-items",{props:["item"],template:"<li>{{item}}</li>"});Vue.component('todo',{template:'<div>\<slot name="todo-title"></slot>\<ul>\<slot name="todo-items"></slot>\</ul>\</div>'});var vm = new Vue({el:"#app",data:{title:"博客",todoItems:['Java','Php','C#']}});
</script>
</body>
</html>
自定义事件
如果想实现,按一个删除键就能删除todo-items对应的一条数据,该如何实现
- 通以上代码不难发现,
数据项在Vue的实例中
,但删除操作要在组件中完成
, 那么组件如何才能删除Vue实例中的数据呢?此时就涉及到参数传递与事件分发了, Vue为我们提供了自定义事件的功能很好的帮助我们解决了这个问题; 使用this.$emit(‘自定义事件名’, 参数) , 操作过程如下:
在vue的实例中增加了methods对象并定义了一个名为removeItems的方法
var vm = new Vue({el:"#app",data:{title:"标题",todoItems:['Java','Php','C#']},methods:{removeItems: function(index){this.todoItems.splice(index,1);}}});
- 因为数据是在vue实例中,所以删除的方法也应该在vue实例中
修改todo-items待办内容组件的代码,增加一个删除按钮,并且绑定事件!
Vue.component("todo-items",{props:['item','index'],//只能绑定绑定当前组件的方法template:'<li>{{index}}--{{item}}<button @click="remove">删除</button></li>',methods:{remove: function(index){//this.$emit()自定义事件分发this.$emit('delete',index);}}});
- this.$emit(‘’,‘’ …)第一个参数是我们的自定义事件名,第二个是相关的参数…
修改todo-items待办内容组件的HTML代码,增加一个自定义事件,比如叫remove,可以和组件的方法绑定,然后绑定到vue的方法!
<div id="app"><todo><todo-title slot="todo-title" :title="title"></todo-title><todo-items slot="todo-items" v-for="(item,index) in todoItems" :item="item" v-bind:index="index" v-on:delete="removeItems"></todo-items></todo>
</div>
完整代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<!--view层,模板-->
<div id="app"><todo><todo-title slot="todo-title" :title="title"></todo-title><todo-items slot="todo-items" v-for="(item,index) in todoItems":item="item" v-bind:index="index"v-on:delete="removeItems"></todo-items></todo>
</div>
<script language="JavaScript" src="static/script/vue.js"></script>
<script type="text/javascript">Vue.component('todo-title',{props:['title'],template:'<div>{{title}}</div>'});Vue.component("todo-items",{props:['item','index'],//只能绑定绑定当前组件的方法template:'<li>{{index}}--{{item}}<button @click="remove(index)">删除</button></li>',methods:{remove: function(index){//this.$emit()自定义事件分发this.$emit('delete',index);}}});Vue.component('todo',{template:'<div>\<slot name="todo-title"></slot>\<ul>\<slot name="todo-items"></slot>\</ul>\</div>'});var vm = new Vue({el:"#app",data:{title:"标题",todoItems:['Java','Php','C#']},methods:{removeItems: function(index){this.todoItems.splice(index,1);}}});
</script>
</body>
</html>