不使用构建工具,DOM内模版解析Vue3+element-plus示例

主要功能点:

  1. 子组件使用v-model,通过computed修改父组件数据(setup语法糖,  从 Vue 3.4 开始,推荐的实现方式是使用 defineModel() 宏)
  2. dom内局部注册组件和使用组件
  3. 使用 ES 模块构建版本

目录结构

index.html

<!DOCTYPE html>
<html lang="zh">
	<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></title>
		<link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css" />
	</head>
	<body>
		<script type="importmap">
			{
			"imports": {
			 "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js",
			"element-plus": "https://unpkg.com/element-plus@2.7.2/dist/index.full.min.mjs",
			"@element-plus/icons-vue": "https://unpkg.com/browse/@element-plus/icons-vue@2.3.1/dist/index.min.js"
			}
		}
		</script>
		<div id="app">
			 <el-tabs type="border-card">
			    <el-tab-pane label="父组件">
					<h3>DOM内模版解析需要遵从html解析行为,使用kebab-case为组件命名,并显式的指定闭合标签</h3>
					<h3>请注意下面讨论只适用于直接在 DOM 中编写模板的情况。如果你使用来自以下来源的字符串模板,就不需要顾虑这些限制了:</h3>
					
					<ul>
						<li>单文件组件</li>
						<li>内联模板字符串 (例如 template: '...')</li>
						<li>&lt;script type="text/x-template"&gt;</li>
					</ul>
					
					<pre>
						<code>
<h2>kebab-case命名法</h2>&lt;component-a&gt;&lt;/component-a&gt; <el-button type="success" circle ><el-icon :size="20"><Check /></el-icon></el-button> 
<h2>camelCase命名法</h2>&lt;componentB>&lt;/componentB&gt;
<h2>PascalCase命名法</h2>&lt;ComponentB&gt;&lt;/componentB&gt;
						</code>
					</pre>
				</el-tab-pane>
			    <el-tab-pane label="组件B">
					<component-b></component-b>
				</el-tab-pane>
			    <el-tab-pane label="组件C">
					<component-c/>
					</el-tab-pane>
			  </el-tabs>
		</div>


		<script type="text/x-template" id="main-template">
	<ComponentA :loginModel="loginModel"  v-model:dialogVisible="loginModel.dialogVisible"/>
	<el-button @click="loginModel.dialogVisible=true">{{ loginModel.title }}</el-button>
		 
		</script>
		<script type="module">
			import {
				createApp,
				ref,
				reactive,
				watchEffect,
				watch
			} from 'vue'
			import ElementPlus from "element-plus"
			import * as ElementPlusIconsVue from '@element-plus/icons-vue'
			import ComponentA from './components/component-a.js'
	
			//定义B组件
			const ComponentB = {
				components: {
					ComponentA,
				},
				setup() {
					const loginModel=ref({
						title:"微信登录",
						signIn:"扫码登录",
						url:"data:image/png;base64,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",
						tip:"使用手机微信扫码登录",
						dialogVisible:false
					})
					return {
						loginModel,
					}
				},
				template: `
			  <ComponentA :loginModel="loginModel"  v-model:dialogVisible="loginModel.dialogVisible"/>
			  <el-button @click="loginModel.dialogVisible=true">{{ loginModel.title }}</el-button>
			  `
			}		
			//定义C组件
			const ComponentC = {
				//局部注册组件
				components: {
					ComponentA,
				},
				setup() {
					const loginModel=ref({
						title:"QQ登录",
						signIn:"扫码登录",
						url:"data:image/png;base64,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",
						tip:"使用手机QQ扫码登录",
						dialogVisible:false
					})
					return {
						loginModel,
					}
				},
				template: "#main-template"
			}


			const app = createApp({
				components: {
					ComponentB,
					ComponentC
				},
				setup() {
					const msg = ref("msg")
					return {
						msg
					}
				}
			})
			for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
			  app.component(key, component)
			}
			app.use(ElementPlus).mount('#app')
			
			
		</script>
	</body>
</html>

component-a.js

import { ref } from 'vue'
import {ElMessageBox} from "element-plus"
export default {
  props:["loginModel","dialogVisible"],
  //emits可省略但不能写错
  emits:["update:dialogVisible"],
  computed:{
	  visible:{
		  get(){
			  return this.dialogVisible
		  },
		  set(val){
			  this.$emit('update:dialogVisible',val)
		  }
	  }
  },
  methods:{
   handleClose (done)  {
	   this.visible=false
	  }
  },
  template: `
   <el-dialog
      v-model="visible"
      :title="loginModel.signIn"
      width="500"
	  style="text-align:center"
      :before-close="handleClose"
    >
    <img :src="loginModel.url"/>
	<p>{{loginModel.tip}}</p>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="visible=false">Cancel</el-button>
        </div>
      </template>
    </el-dialog>
  `
}

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值